about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml17
-rw-r--r--Cargo.lock13
-rw-r--r--Cargo.toml57
-rw-r--r--compiler/rustc_abi/src/lib.rs5
-rw-r--r--compiler/rustc_arena/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs4
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs12
-rw-r--r--compiler/rustc_ast/src/token.rs9
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs8
-rw-r--r--compiler/rustc_ast_ir/src/lib.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs16
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_attr_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/lib.rs2
-rw-r--r--compiler/rustc_baked_icu_data/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1487
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs8
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/command.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs29
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs48
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs52
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs148
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs124
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs3
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs54
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs6
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/Cargo.toml5
-rw-r--r--compiler/rustc_data_structures/src/graph/tests.rs4
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/marker.rs2
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs95
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync/parallel.rs2
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/tests.rs2
-rw-r--r--compiler/rustc_driver/src/lib.rs1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs3
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_error_messages/src/lib.rs7
-rw-r--r--compiler/rustc_errors/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/base.rs49
-rw-r--r--compiler/rustc_expand/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs14
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs49
-rw-r--r--compiler/rustc_feature/src/lib.rs1
-rw-r--r--compiler/rustc_fluent_macro/src/lib.rs1
-rw-r--r--compiler/rustc_graphviz/src/lib.rs1
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/delegation.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs14
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs2
-rw-r--r--compiler/rustc_incremental/src/lib.rs2
-rw-r--r--compiler/rustc_index/src/lib.rs1
-rw-r--r--compiler/rustc_index_macros/src/newtype.rs2
-rw-r--r--compiler/rustc_infer/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/interface.rs6
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs4
-rw-r--r--compiler/rustc_lexer/src/lib.rs1
-rw-r--r--compiler/rustc_lint/src/builtin.rs6
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs9
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp9
-rw-r--r--compiler/rustc_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs2
-rw-r--r--compiler/rustc_metadata/src/lib.rs6
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs63
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/hir/map.rs310
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs117
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs20
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs7
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs16
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs117
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs3
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs5
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs9
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/autodiff.rs16
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs51
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/project_goals.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/search_graph.rs30
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs3
-rw-r--r--compiler/rustc_parse/src/parser/item.rs13
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs12
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs12
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs60
-rw-r--r--compiler/rustc_parse_format/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs19
-rw-r--r--compiler/rustc_passes/src/dead.rs6
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/entry.rs6
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs7
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/loops.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs6
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_pattern_analysis/tests/common/mod.rs14
-rw-r--r--compiler/rustc_privacy/src/lib.rs8
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs31
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs14
-rw-r--r--compiler/rustc_resolve/messages.ftl12
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs30
-rw-r--r--compiler/rustc_resolve/src/errors.rs18
-rw-r--r--compiler/rustc_resolve/src/ident.rs61
-rw-r--r--compiler/rustc_resolve/src/late.rs73
-rw-r--r--compiler/rustc_resolve/src/lib.rs10
-rw-r--r--compiler/rustc_sanitizers/src/lib.rs2
-rw-r--r--compiler/rustc_serialize/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/filesearch.rs48
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs3
-rw-r--r--compiler/rustc_smir/src/lib.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/base/fuchsia.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs34
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.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_fuchsia.rs22
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs5
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs25
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs16
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_traits/src/lib.rs1
-rw-r--r--compiler/rustc_transmute/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs6
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs8
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs165
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs19
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/core/Cargo.toml2
-rw-r--r--library/core/src/ffi/va_list.rs6
-rw-r--r--library/core/src/intrinsics/mod.rs652
-rw-r--r--library/core/src/intrinsics/simd.rs136
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/net/socket_addr.rs32
-rw-r--r--library/panic_abort/Cargo.toml2
-rw-r--r--library/panic_unwind/Cargo.toml2
-rw-r--r--library/proc_macro/Cargo.toml2
-rw-r--r--library/profiler_builtins/Cargo.toml2
-rw-r--r--library/rustc-std-workspace-alloc/Cargo.toml2
-rw-r--r--library/rustc-std-workspace-core/Cargo.toml2
-rw-r--r--library/rustc-std-workspace-std/Cargo.toml2
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/collections/hash/map.rs497
-rw-r--r--library/std/src/collections/hash/map/tests.rs93
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/error.rs4
-rw-r--r--library/std/src/io/tests.rs16
-rw-r--r--library/std/src/keyword_docs.rs2
-rw-r--r--library/std/src/net/tcp.rs3
-rw-r--r--library/std/src/net/udp.rs3
-rw-r--r--library/std/src/os/fd/mod.rs1
-rw-r--r--library/std/src/os/fd/owned.rs28
-rw-r--r--library/std/src/os/fd/raw.rs10
-rw-r--r--library/std/src/os/mod.rs4
-rw-r--r--library/std/src/os/trusty/io/mod.rs4
-rw-r--r--library/std/src/os/trusty/mod.rs3
-rw-r--r--library/std/src/os/unix/fs.rs124
-rw-r--r--library/std/src/os/windows/process.rs2
-rw-r--r--library/std/src/process.rs3
-rw-r--r--library/std/src/sys/alloc/mod.rs1
-rw-r--r--library/std/src/sys/fs/uefi.rs99
-rw-r--r--library/std/src/sys/pal/mod.rs3
-rw-r--r--library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs64
-rw-r--r--library/std/src/sys/pal/sgx/abi/usercalls/mod.rs17
-rw-r--r--library/std/src/sys/pal/sgx/fd.rs2
-rw-r--r--library/std/src/sys/pal/trusty/mod.rs21
-rw-r--r--library/std/src/sys/random/mod.rs3
-rw-r--r--library/std/src/sys/random/trusty.rs7
-rw-r--r--library/std/src/sys/stdio/mod.rs3
-rw-r--r--library/std/src/sys/stdio/sgx.rs33
-rw-r--r--library/std/src/sys/stdio/trusty.rs81
-rw-r--r--library/std/src/sys/thread_local/mod.rs2
-rw-r--r--library/std/tests/floats/f16.rs84
-rw-r--r--library/sysroot/Cargo.toml2
-rw-r--r--library/test/Cargo.toml2
-rw-r--r--library/unwind/Cargo.toml2
-rw-r--r--library/windows_targets/Cargo.toml2
-rw-r--r--library/windows_targets/src/lib.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs43
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs6
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs40
-rw-r--r--src/bootstrap/src/core/builder/mod.rs5
-rw-r--r--src/bootstrap/src/core/config/mod.rs2
-rw-r--r--src/bootstrap/src/core/download.rs2
-rw-r--r--src/bootstrap/src/lib.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/exec.rs5
-rw-r--r--src/bootstrap/src/utils/metrics.rs5
-rw-r--r--src/bootstrap/src/utils/tarball.rs3
-rw-r--r--src/ci/citool/src/jobs.rs5
-rw-r--r--src/ci/citool/tests/jobs.rs2
-rw-r--r--src/ci/citool/tests/test-jobs.yml1
-rw-r--r--src/ci/github-actions/jobs.yml2
-rwxr-xr-xsrc/ci/run.sh23
-rw-r--r--src/doc/rustc-dev-guide/src/hir.md4
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/trusty.md6
-rw-r--r--src/etc/rust_analyzer_eglot.el1
-rw-r--r--src/etc/rust_analyzer_helix.toml1
-rw-r--r--src/etc/rust_analyzer_settings.json1
-rw-r--r--src/etc/rust_analyzer_zed.json1
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs43
-rw-r--r--src/librustdoc/clean/types.rs17
-rw-r--r--src/librustdoc/config.rs11
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/librustdoc/doctest/rust.rs2
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/static/js/main.js64
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts25
-rw-r--r--src/librustdoc/json/conversions.rs79
-rw-r--r--src/librustdoc/json/ids.rs122
-rw-r--r--src/librustdoc/json/mod.rs12
-rw-r--r--src/librustdoc/visit_ast.rs9
-rw-r--r--src/rustdoc-json-types/lib.rs20
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--src/tools/build-manifest/src/versions.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/four_forward_slashes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_if.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.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/no_mangle_with_rust_abi.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/op_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/dump_hir.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs4
-rw-r--r--src/tools/compiletest/src/common.rs10
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs3
-rw-r--r--src/tools/miri/src/machine.rs107
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs2
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs2
-rw-r--r--src/tools/rls/Cargo.toml8
-rw-r--r--src/tools/rls/README.md6
-rw-r--r--src/tools/rls/src/main.rs102
-rw-r--r--src/tools/rustbook/Cargo.lock12
-rw-r--r--src/tools/rustbook/Cargo.toml2
-rw-r--r--src/tools/rustbook/src/main.rs1
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/walk.rs2
-rw-r--r--src/tools/x/Cargo.lock7
-rw-r--r--tests/assembly/naked-functions/aarch64-naked-fn-no-bti-prolog.rs (renamed from tests/assembly/aarch64-naked-fn-no-bti-prolog.rs)0
-rw-r--r--tests/assembly/naked-functions/aix.rs35
-rw-r--r--tests/assembly/naked-functions/wasm32.rs (renamed from tests/assembly/wasm32-naked-fn.rs)0
-rw-r--r--tests/assembly/naked-functions/x86_64-naked-fn-no-cet-prolog.rs (renamed from tests/assembly/x86_64-naked-fn-no-cet-prolog.rs)0
-rw-r--r--tests/codegen/enum/enum-two-variants-match.rs37
-rw-r--r--tests/codegen/intrinsics/cold_path2.rs4
-rw-r--r--tests/codegen/match-optimizes-away.rs11
-rw-r--r--tests/codegen/naked-fn/naked-functions.rs72
-rw-r--r--tests/codegen/try_question_mark_nop.rs6
-rw-r--r--tests/mir-opt/global_asm.rs9
-rw-r--r--tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir9
-rw-r--r--tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff10
-rw-r--r--tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff6
-rw-r--r--tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff6
-rw-r--r--tests/run-make/core-no-fp-fmt-parse/rmake.rs2
-rw-r--r--tests/rustdoc-json/impl-trait-precise-capturing.rs6
-rw-r--r--tests/ui-fulldeps/run-compiler-twice.rs2
-rw-r--r--tests/ui/associated-type-bounds/hrtb.rs3
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr4
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/display.stderr8
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/rendering.fixed15
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/rendering.rs14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/rendering.stderr12
-rw-r--r--tests/ui/associated-type-bounds/supertrait-defines-ty.rs3
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-const-param.rs8
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-parent-param.rs8
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr9
-rw-r--r--tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr6
-rw-r--r--tests/ui/const-generics/defaults/forward-declared.rs8
-rw-r--r--tests/ui/const-generics/defaults/forward-declared.stderr16
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs4
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr9
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr15
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs5
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr4
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr4
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs2
-rw-r--r--tests/ui/consts/const-unsized.stderr12
-rw-r--r--tests/ui/delegation/fn-header-variadic.rs25
-rw-r--r--tests/ui/delegation/fn-header-variadic.stderr22
-rw-r--r--tests/ui/delegation/fn-header.rs11
-rw-r--r--tests/ui/delegation/foreign-fn.rs22
-rw-r--r--tests/ui/delegation/foreign-fn.stderr27
-rw-r--r--tests/ui/delegation/ice-issue-138362.rs15
-rw-r--r--tests/ui/delegation/ice-issue-138362.stderr19
-rw-r--r--tests/ui/error-codes/E0128.stderr4
-rw-r--r--tests/ui/generics/generic-non-trailing-defaults.rs2
-rw-r--r--tests/ui/generics/generic-non-trailing-defaults.stderr4
-rw-r--r--tests/ui/generics/generic-type-params-forward-mention.rs2
-rw-r--r--tests/ui/generics/generic-type-params-forward-mention.stderr4
-rw-r--r--tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr12
-rw-r--r--tests/ui/issues/issue-18183.stderr4
-rw-r--r--tests/ui/issues/issue-26812.rs2
-rw-r--r--tests/ui/issues/issue-26812.stderr4
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr7
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.rs2
-rw-r--r--tests/ui/macros/macro-stmt-2.rs11
-rw-r--r--tests/ui/macros/nonterminal-matching.rs4
-rw-r--r--tests/ui/macros/nonterminal-matching.stderr6
-rw-r--r--tests/ui/macros/std-2024-macros.rs13
-rw-r--r--tests/ui/proc-macro/expand-to-derive.stdout80
-rw-r--r--tests/ui/proc-macro/nodelim-groups.rs13
-rw-r--r--tests/ui/proc-macro/nodelim-groups.stdout15
-rw-r--r--tests/ui/rmeta/rmeta_bin-pass.rs14
-rw-r--r--tests/ui/rmeta/rmeta_bin.rs14
-rw-r--r--tests/ui/rmeta/rmeta_bin.stderr4
-rw-r--r--tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs9
-rw-r--r--tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs9
-rw-r--r--tests/ui/runtime/signal-alternate-stack-cleanup.rs9
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs2
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr29
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs8
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs21
-rw-r--r--tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs21
-rw-r--r--tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr11
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs7
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr54
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs7
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr54
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr4
494 files changed, 4537 insertions, 4054 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f166e0c0b41..96c0955e871 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -68,6 +68,7 @@ jobs:
     timeout-minutes: 360
     env:
       CI_JOB_NAME: ${{ matrix.name }}
+      CI_JOB_DOC_URL: ${{ matrix.doc_url }}
       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 }}
@@ -190,8 +191,20 @@ jobs:
           CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build
 
       - name: run the build
-        # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
-        run: src/ci/scripts/run-build-from-ci.sh 2>&1
+        run: |
+          set +e
+          # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
+          src/ci/scripts/run-build-from-ci.sh 2>&1
+          STATUS=$?
+          set -e
+
+          if [[ "$STATUS" -ne 0 && -n "$CI_JOB_DOC_URL" ]]; then
+            echo "****************************************************************************"
+            echo "To find more information about this job, visit the following URL:"
+            echo "$CI_JOB_DOC_URL"
+            echo "****************************************************************************"
+          fi
+          exit ${STATUS}
         env:
           AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }}
           AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}
diff --git a/Cargo.lock b/Cargo.lock
index a804638f702..6d252ca8c82 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1491,6 +1491,7 @@ version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 dependencies = [
+ "allocator-api2",
  "foldhash",
  "serde",
 ]
@@ -3045,13 +3046,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rls"
-version = "2.0.0"
-dependencies = [
- "serde_json",
-]
-
-[[package]]
 name = "run_make_support"
 version = "0.2.0"
 dependencies = [
@@ -3492,6 +3486,7 @@ dependencies = [
  "either",
  "elsa",
  "ena",
+ "hashbrown 0.15.2",
  "indexmap",
  "jobserver",
  "libc",
@@ -6444,6 +6439,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 
 [[package]]
+name = "x"
+version = "0.1.1"
+
+[[package]]
 name = "xattr"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 20a43aaaeeb..16ff0f61593 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,51 +1,53 @@
 [workspace]
 resolver = "2"
 members = [
+# tidy-alphabetical-start
   "compiler/rustc",
   "src/build_helper",
   "src/etc/test-float-parse",
-  "src/rustc-std-workspace/rustc-std-workspace-core",
   "src/rustc-std-workspace/rustc-std-workspace-alloc",
+  "src/rustc-std-workspace/rustc-std-workspace-core",
   "src/rustc-std-workspace/rustc-std-workspace-std",
   "src/rustdoc-json-types",
+  "src/tools/build-manifest",
+  "src/tools/bump-stage0",
   "src/tools/cargotest",
   "src/tools/clippy",
   "src/tools/clippy/clippy_dev",
+  "src/tools/collect-license-metadata",
   "src/tools/compiletest",
-  "src/tools/run-make-support",
+  "src/tools/coverage-dump",
+  "src/tools/features-status-dump",
+  "src/tools/generate-copyright",
+  "src/tools/generate-windows-sys",
+  "src/tools/html-checker",
+  "src/tools/jsondocck",
+  "src/tools/jsondoclint",
   "src/tools/linkchecker",
   "src/tools/lint-docs",
+  "src/tools/lld-wrapper",
+  "src/tools/llvm-bitcode-linker",
+  "src/tools/miri",
+  "src/tools/miri/cargo-miri",
   "src/tools/miropt-test-tools",
-  "src/tools/unstable-book-gen",
-  "src/tools/tidy",
-  "src/tools/tier-check",
-  "src/tools/build-manifest",
+  "src/tools/opt-dist",
   "src/tools/remote-test-client",
   "src/tools/remote-test-server",
+  "src/tools/replace-version-placeholder",
+  "src/tools/run-make-support",
   "src/tools/rust-installer",
   "src/tools/rustdoc",
-  "src/tools/rls",
-  "src/tools/rustfmt",
-  "src/tools/miri",
-  "src/tools/miri/cargo-miri",
+  "src/tools/rustdoc-gui-test",
   "src/tools/rustdoc-themes",
-  "src/tools/unicode-table-generator",
-  "src/tools/jsondocck",
-  "src/tools/jsondoclint",
-  "src/tools/llvm-bitcode-linker",
-  "src/tools/html-checker",
-  "src/tools/bump-stage0",
-  "src/tools/replace-version-placeholder",
-  "src/tools/lld-wrapper",
-  "src/tools/collect-license-metadata",
-  "src/tools/generate-copyright",
+  "src/tools/rustfmt",
   "src/tools/suggest-tests",
-  "src/tools/generate-windows-sys",
-  "src/tools/rustdoc-gui-test",
-  "src/tools/opt-dist",
-  "src/tools/coverage-dump",
+  "src/tools/tidy",
+  "src/tools/tier-check",
+  "src/tools/unicode-table-generator",
+  "src/tools/unstable-book-gen",
   "src/tools/wasm-component-ld",
-  "src/tools/features-status-dump",
+  "src/tools/x",
+# tidy-alphabetical-end
 ]
 
 exclude = [
@@ -56,11 +58,6 @@ exclude = [
   "tests/rustdoc-gui",
   # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
   "obj",
-  # The `x` binary is a thin wrapper that calls `x.py`, which initializes
-  # submodules, before which workspace members cannot be invoked because
-  # not all `Cargo.toml` files are available, so we exclude the `x` binary,
-  # so it can be invoked before the current checkout is set up.
-  "src/tools/x",
 ]
 
 [profile.release.package.rustc-rayon-core]
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 1b737582009..d2f663999ba 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -5,7 +5,6 @@
 #![cfg_attr(feature = "nightly", feature(rustc_attrs))]
 #![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
 #![cfg_attr(feature = "nightly", feature(step_trait))]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 /*! ABI handling for rustc
@@ -803,7 +802,7 @@ impl Align {
     }
 
     #[inline]
-    pub fn bytes(self) -> u64 {
+    pub const fn bytes(self) -> u64 {
         1 << self.pow2
     }
 
@@ -813,7 +812,7 @@ impl Align {
     }
 
     #[inline]
-    pub fn bits(self) -> u64 {
+    pub const fn bits(self) -> u64 {
         self.bytes() * 8
     }
 
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 3b44e996358..6aaac072e4b 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -23,7 +23,6 @@
 #![feature(maybe_uninit_slice)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::alloc::Layout;
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index a37c0f92b12..849cc650e9d 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -209,16 +209,12 @@ impl HasTokens for Attribute {
 impl HasTokens for Nonterminal {
     fn tokens(&self) -> Option<&LazyAttrTokenStream> {
         match self {
-            Nonterminal::NtItem(item) => item.tokens(),
-            Nonterminal::NtStmt(stmt) => stmt.tokens(),
             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::NtItem(item) => item.tokens_mut(),
-            Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
             Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
         }
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 6372c66050e..da510e4967d 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -6,6 +6,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(deny(warnings)))
@@ -19,7 +20,6 @@
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 #![feature(stmt_expr_attributes)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod util {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index fc31912283a..4a1636e6aec 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -895,19 +895,7 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
 // multiple items there....
 fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
     match nt {
-        token::NtItem(item) => visit_clobber(item, |item| {
-            // This is probably okay, because the only visitors likely to
-            // peek inside interpolated nodes will be renamings/markings,
-            // which map single items to single items.
-            vis.flat_map_item(item).expect_one("expected visitor to produce exactly one item")
-        }),
         token::NtBlock(block) => vis.visit_block(block),
-        token::NtStmt(stmt) => visit_clobber(stmt, |stmt| {
-            // See reasoning above.
-            stmt.map(|stmt| {
-                vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item")
-            })
-        }),
         token::NtExpr(expr) => vis.visit_expr(expr),
         token::NtLiteral(expr) => vis.visit_expr(expr),
     }
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index ff1edad725a..f7cd63aaaf8 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -870,6 +870,7 @@ 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 {
+        #[allow(irrefutable_let_patterns)] // FIXME: temporary
         if let Interpolated(nt) = &self.kind
             && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt
         {
@@ -1103,9 +1104,7 @@ pub enum NtExprKind {
 #[derive(Clone, Encodable, Decodable)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
-    NtItem(P<ast::Item>),
     NtBlock(P<ast::Block>),
-    NtStmt(P<ast::Stmt>),
     NtExpr(P<ast::Expr>),
     NtLiteral(P<ast::Expr>),
 }
@@ -1196,18 +1195,14 @@ impl fmt::Display for NonterminalKind {
 impl Nonterminal {
     pub fn use_span(&self) -> Span {
         match self {
-            NtItem(item) => item.span,
             NtBlock(block) => block.span,
-            NtStmt(stmt) => stmt.span,
             NtExpr(expr) | NtLiteral(expr) => expr.span,
         }
     }
 
     pub fn descr(&self) -> &'static str {
         match self {
-            NtItem(..) => "item",
             NtBlock(..) => "block",
-            NtStmt(..) => "statement",
             NtExpr(..) => "expression",
             NtLiteral(..) => "literal",
         }
@@ -1227,9 +1222,7 @@ impl PartialEq for Nonterminal {
 impl fmt::Debug for Nonterminal {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            NtItem(..) => f.pad("NtItem(..)"),
             NtBlock(..) => f.pad("NtBlock(..)"),
-            NtStmt(..) => f.pad("NtStmt(..)"),
             NtExpr(..) => f.pad("NtExpr(..)"),
             NtLiteral(..) => f.pad("NtLiteral(..)"),
         }
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index b9b20cf9376..bdd244be6d1 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -23,7 +23,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
 
-use crate::ast::{AttrStyle, StmtKind};
+use crate::ast::AttrStyle;
 use crate::ast_traits::{HasAttrs, HasTokens};
 use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind};
 use crate::{AttrVec, Attribute};
@@ -461,13 +461,7 @@ impl TokenStream {
 
     pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
         match nt {
-            Nonterminal::NtItem(item) => TokenStream::from_ast(item),
             Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
-            Nonterminal::NtStmt(stmt) if let StmtKind::Empty = stmt.kind => {
-                // FIXME: Properly collect tokens for empty statements.
-                TokenStream::token_alone(token::Semi, stmt.span)
-            }
-            Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt),
             Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
         }
     }
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index 9884e191ea7..6d05cd18cec 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -9,7 +9,6 @@
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 #![cfg_attr(feature = "nightly", feature(never_type))]
 #![cfg_attr(feature = "nightly", feature(rustc_attrs))]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 #[cfg(feature = "nightly")]
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 87af7959a88..65784af92c7 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
         if let Some(asm_arch) = asm_arch {
             // Inline assembly is currently only stable for these architectures.
+            // (See also compiletest's `has_asm_support`.)
             let is_stable = matches!(
                 asm_arch,
                 asm::InlineAsmArch::X86
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 571172be4ed..efc1fa05c5f 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -190,14 +190,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::FnSig<'hir> {
         let header = if let Some(local_sig_id) = sig_id.as_local() {
             match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
-                Some(sig) => self.lower_fn_header(
-                    sig.header,
+                Some(sig) => {
+                    let parent = self.tcx.parent(sig_id);
                     // HACK: we override the default safety instead of generating attributes from the ether.
                     // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
                     // and here we need the hir attributes.
-                    if sig.target_feature { hir::Safety::Unsafe } else { hir::Safety::Safe },
-                    &[],
-                ),
+                    let default_safety =
+                        if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod {
+                            hir::Safety::Unsafe
+                        } else {
+                            hir::Safety::Safe
+                        };
+                    self.lower_fn_header(sig.header, default_safety, &[])
+                }
                 None => self.generate_header_error(),
             }
         } else {
@@ -330,6 +335,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             .unwrap_or_default()
             && delegation.qself.is_none()
             && !has_generic_args
+            && !args.is_empty()
         {
             let ast_segment = delegation.path.segments.last().unwrap();
             let segment = self.lower_path_segment(
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 1bf85bbf26c..c7d37e2704d 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,6 +32,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -39,7 +40,6 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::sync::Arc;
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index b4ed70d83e5..093199cf342 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -10,7 +10,6 @@
 #![feature(iter_is_partitioned)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod ast_validation;
diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs
index 602ab69ee5b..84d9ce278a2 100644
--- a/compiler/rustc_ast_pretty/src/lib.rs
+++ b/compiler/rustc_ast_pretty/src/lib.rs
@@ -3,7 +3,6 @@
 #![doc(rust_logo)]
 #![feature(box_patterns)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod helpers;
diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index 389d8c2413b..bbd3308809c 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -3,7 +3,6 @@
 #![doc(rust_logo)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod attributes;
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index 386f2c98447..a7465847e18 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -77,10 +77,10 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(rust_logo)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 #[macro_use]
diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs
index f86a9db61c6..f3f6522f575 100644
--- a/compiler/rustc_baked_icu_data/src/lib.rs
+++ b/compiler/rustc_baked_icu_data/src/lib.rs
@@ -23,6 +23,7 @@
 // tidy-alphabetical-start
 #![allow(elided_lifetimes_in_paths)]
 #![allow(internal_features)]
+#![allow(unreachable_pub)] // because this crate is mostly generated code
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
 // #![warn(unreachable_pub)] // don't use because this crate is mostly generated code
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index d1f238331d5..208d510db2e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -505,7 +505,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     let var_id =
                         self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
 
-                    Some(self.infcx.tcx.hir().name(var_id).to_string())
+                    Some(self.infcx.tcx.hir_name(var_id).to_string())
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
@@ -1124,7 +1124,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             def_id, target_place, places
         );
         let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
-        let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
+        let expr = &self.infcx.tcx.hir_expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let &hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
             for (captured_place, place) in
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 145137f9236..3951b467961 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -698,7 +698,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         if !matches!(k, hir::AssocItemKind::Fn { .. }) {
                             continue;
                         }
-                        if self.infcx.tcx.hir().name(hi) != self.infcx.tcx.hir().name(my_hir) {
+                        if self.infcx.tcx.hir_name(hi) != self.infcx.tcx.hir_name(my_hir) {
                             continue;
                         }
                         f_in_trait_opt = Some(hi);
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
index 876b8f214b0..7192a889adc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
@@ -105,7 +105,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
                     if let Some(opaque_def_id) = opaque_def_id.as_local()
                         && let hir::OpaqueTyOrigin::FnReturn { parent, .. } =
-                            tcx.hir().expect_opaque_ty(opaque_def_id).origin
+                            tcx.hir_expect_opaque_ty(opaque_def_id).origin
                     {
                         if let Some(sugg) = impl_trait_overcapture_suggestion(
                             tcx,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index a15f9744bf3..412aaf70c3f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -343,7 +343,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                         }
                     };
                     let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
-                        tcx.hir().expect_expr(self.mir_hir_id()).kind
+                        tcx.hir_expect_expr(self.mir_hir_id()).kind
                     else {
                         bug!("Closure is not defined by a closure expr");
                     };
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 191c0444c74..693d22abbe6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -69,7 +69,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let upvar_hir_id = upvars[upvar_index].get_root_variable();
         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_name = tcx.hir_name(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 64a533e05ff..7ae7936a2a2 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2,6 +2,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -13,7 +14,6 @@
 #![feature(rustdoc_internals)]
 #![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::borrow::Cow;
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9d5022f2bef..d2eb7a52f78 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -156,6 +156,7 @@ pub(crate) fn type_check<'a, 'tcx>(
         infcx,
         last_span: body.span,
         body,
+        promoted,
         user_type_annotations: &body.user_type_annotations,
         region_bound_pairs,
         known_type_outlives_obligations,
@@ -170,11 +171,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     };
 
     typeck.check_user_type_annotations();
-
-    let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
-    verifier.visit_body(body);
-
-    typeck.typeck_mir();
+    typeck.visit_body(body);
     typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
     typeck.check_signature_annotation();
 
@@ -212,370 +209,6 @@ enum FieldAccessError {
     OutOfRange { field_count: usize },
 }
 
-/// Verifies that MIR types are sane.
-///
-/// FIXME: This should be merged with the actual `TypeChecker`.
-struct TypeVerifier<'a, 'b, 'tcx> {
-    typeck: &'a mut TypeChecker<'b, 'tcx>,
-    promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
-    last_span: Span,
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
-    fn visit_span(&mut self, span: Span) {
-        if !span.is_dummy() {
-            self.last_span = span;
-        }
-    }
-
-    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
-        self.super_place(place, context, location);
-        let tcx = self.tcx();
-        let place_ty = place.ty(self.body(), tcx);
-        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-            let trait_ref = ty::TraitRef::new(
-                tcx,
-                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
-                [place_ty.ty],
-            );
-
-            // To have a `Copy` operand, the type `T` of the
-            // value must be `Copy`. Note that we prove that `T: Copy`,
-            // rather than using the `is_copy_modulo_regions`
-            // test. This is important because
-            // `is_copy_modulo_regions` ignores the resulting region
-            // obligations and assumes they pass. This can result in
-            // bounds from `Copy` impls being unsoundly ignored (e.g.,
-            // #29149). Note that we decide to use `Copy` before knowing
-            // whether the bounds fully apply: in effect, the rule is
-            // that if a value of some type could implement `Copy`, then
-            // it must.
-            self.typeck.prove_trait_ref(
-                trait_ref,
-                location.to_locations(),
-                ConstraintCategory::CopyBound,
-            );
-        }
-    }
-
-    fn visit_projection_elem(
-        &mut self,
-        place: PlaceRef<'tcx>,
-        elem: PlaceElem<'tcx>,
-        context: PlaceContext,
-        location: Location,
-    ) {
-        let tcx = self.tcx();
-        let base_ty = place.ty(self.body(), tcx);
-        match elem {
-            // All these projections don't add any constraints, so there's nothing to
-            // do here. We check their invariants in the MIR validator after all.
-            ProjectionElem::Deref
-            | ProjectionElem::Index(_)
-            | ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::Subslice { .. }
-            | ProjectionElem::Downcast(..) => {}
-            ProjectionElem::Field(field, fty) => {
-                let fty = self.typeck.normalize(fty, location);
-                let ty = base_ty.field_ty(tcx, field);
-                let ty = self.typeck.normalize(ty, location);
-                debug!(?fty, ?ty);
-
-                if let Err(terr) = self.typeck.relate_types(
-                    ty,
-                    context.ambient_variance(),
-                    fty,
-                    location.to_locations(),
-                    ConstraintCategory::Boring,
-                ) {
-                    span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
-                }
-            }
-            ProjectionElem::OpaqueCast(ty) => {
-                let ty = self.typeck.normalize(ty, location);
-                self.typeck
-                    .relate_types(
-                        ty,
-                        context.ambient_variance(),
-                        base_ty.ty,
-                        location.to_locations(),
-                        ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
-                    )
-                    .unwrap();
-            }
-            ProjectionElem::UnwrapUnsafeBinder(ty) => {
-                let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
-                    unreachable!();
-                };
-                let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
-                    self.body().source_info(location).span,
-                    BoundRegionConversionTime::HigherRankedType,
-                    binder_ty.into(),
-                );
-                self.typeck
-                    .relate_types(
-                        ty,
-                        context.ambient_variance(),
-                        found_ty,
-                        location.to_locations(),
-                        ConstraintCategory::Boring,
-                    )
-                    .unwrap();
-            }
-            ProjectionElem::Subtype(_) => {
-                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
-        self.super_const_operand(constant, location);
-        let ty = constant.const_.ty();
-
-        self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| {
-            let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region);
-            self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location);
-        });
-
-        let locations = location.to_locations();
-        if let Some(annotation_index) = constant.user_ty {
-            if let Err(terr) = self.typeck.relate_type_and_user_type(
-                constant.const_.ty(),
-                ty::Invariant,
-                &UserTypeProjection { base: annotation_index, projs: vec![] },
-                locations,
-                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
-            ) {
-                let annotation = &self.typeck.user_type_annotations[annotation_index];
-                span_mirbug!(
-                    self,
-                    constant,
-                    "bad constant user type {:?} vs {:?}: {:?}",
-                    annotation,
-                    constant.const_.ty(),
-                    terr,
-                );
-            }
-        } else {
-            let tcx = self.tcx();
-            let maybe_uneval = match constant.const_ {
-                Const::Ty(_, ct) => match ct.kind() {
-                    ty::ConstKind::Unevaluated(uv) => {
-                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
-                    }
-                    _ => None,
-                },
-                Const::Unevaluated(uv, _) => Some(uv),
-                _ => None,
-            };
-
-            if let Some(uv) = maybe_uneval {
-                if let Some(promoted) = uv.promoted {
-                    let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
-                                     promoted: &Body<'tcx>,
-                                     ty,
-                                     san_ty| {
-                        if let Err(terr) = verifier.typeck.eq_types(
-                            ty,
-                            san_ty,
-                            locations,
-                            ConstraintCategory::Boring,
-                        ) {
-                            span_mirbug!(
-                                verifier,
-                                promoted,
-                                "bad promoted type ({:?}: {:?}): {:?}",
-                                ty,
-                                san_ty,
-                                terr
-                            );
-                        };
-                    };
-
-                    let promoted_body = &self.promoted[promoted];
-                    self.verify_promoted(promoted_body, location);
-
-                    let promoted_ty = promoted_body.return_ty();
-                    check_err(self, promoted_body, ty, promoted_ty);
-                } else {
-                    self.typeck.ascribe_user_type(
-                        constant.const_.ty(),
-                        ty::UserType::new(ty::UserTypeKind::TypeOf(
-                            uv.def,
-                            UserArgs { args: uv.args, user_self_ty: None },
-                        )),
-                        locations.span(self.typeck.body),
-                    );
-                }
-            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
-                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
-                let normalized_ty = self.typeck.normalize(unnormalized_ty, locations);
-                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
-
-                if let Err(terr) = self.typeck.eq_types(
-                    literal_ty,
-                    normalized_ty,
-                    locations,
-                    ConstraintCategory::Boring,
-                ) {
-                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
-                }
-            }
-
-            if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
-                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
-                self.typeck.normalize_and_prove_instantiated_predicates(
-                    def_id,
-                    instantiated_predicates,
-                    locations,
-                );
-
-                assert!(!matches!(
-                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
-                    Some(DefKind::Impl { of_trait: true })
-                ));
-                self.typeck.prove_predicates(
-                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
-                    locations,
-                    ConstraintCategory::Boring,
-                );
-            }
-        }
-    }
-
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        self.super_local_decl(local, local_decl);
-
-        for user_ty in
-            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
-        {
-            let span = self.typeck.user_type_annotations[user_ty.base].span;
-
-            let ty = if local_decl.is_nonref_binding() {
-                local_decl.ty
-            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
-                // If we have a binding of the form `let ref x: T = ..`
-                // then remove the outermost reference so we can check the
-                // type annotation for the remaining type.
-                rty
-            } else {
-                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
-            };
-
-            if let Err(terr) = self.typeck.relate_type_and_user_type(
-                ty,
-                ty::Invariant,
-                user_ty,
-                Locations::All(span),
-                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
-            ) {
-                span_mirbug!(
-                    self,
-                    local,
-                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
-                    local,
-                    local_decl.ty,
-                    local_decl.user_ty,
-                    terr,
-                );
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_body(&mut self, body: &Body<'tcx>) {
-        debug_assert!(std::ptr::eq(self.typeck.body, body));
-        // We intentionally do not recurse into `body.required_consts` or
-        // `body.mentioned_items` here as the MIR at this phase should still
-        // refer to all items and we don't want to check them multiple times.
-
-        for (local, local_decl) in body.local_decls.iter_enumerated() {
-            self.visit_local_decl(local, local_decl);
-        }
-
-        for (block, block_data) in body.basic_blocks.iter_enumerated() {
-            let mut location = Location { block, statement_index: 0 };
-            for stmt in &block_data.statements {
-                if !stmt.source_info.span.is_dummy() {
-                    self.last_span = stmt.source_info.span;
-                }
-                self.visit_statement(stmt, location);
-                location.statement_index += 1;
-            }
-
-            self.visit_terminator(block_data.terminator(), location);
-        }
-    }
-}
-
-impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
-    fn body(&self) -> &Body<'tcx> {
-        self.typeck.body
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.typeck.infcx.tcx
-    }
-
-    fn verify_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
-        // Determine the constraints from the promoted MIR by running the type
-        // checker on the promoted MIR, then transfer the constraints back to
-        // the main MIR, changing the locations to the provided location.
-
-        let parent_body = mem::replace(&mut self.typeck.body, promoted_body);
-
-        // Use new sets of constraints and closure bounds so that we can
-        // modify their locations.
-        let polonius_facts = &mut None;
-        let mut constraints = Default::default();
-        let mut liveness_constraints =
-            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
-        // Don't try to add borrow_region facts for the promoted MIR
-
-        let mut swap_constraints = |this: &mut Self| {
-            mem::swap(this.typeck.polonius_facts, polonius_facts);
-            mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
-            mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
-        };
-
-        swap_constraints(self);
-
-        self.visit_body(promoted_body);
-
-        self.typeck.typeck_mir();
-
-        self.typeck.body = parent_body;
-        // Merge the outlives constraints back in, at the given location.
-        swap_constraints(self);
-
-        let locations = location.to_locations();
-        for constraint in constraints.outlives().iter() {
-            let mut constraint = *constraint;
-            constraint.locations = locations;
-            if let ConstraintCategory::Return(_)
-            | ConstraintCategory::UseAsConst
-            | ConstraintCategory::UseAsStatic = constraint.category
-            {
-                // "Returning" from a promoted is an assignment to a
-                // temporary from the user's point of view.
-                constraint.category = ConstraintCategory::Boring;
-            }
-            self.typeck.constraints.outlives_constraints.push(constraint)
-        }
-        // If the region is live at least one location in the promoted MIR,
-        // then add a liveness constraint to the main MIR for this region
-        // at the location provided as an argument to this method
-        //
-        // add_location doesn't care about ordering so not a problem for the live regions to be
-        // unordered.
-        #[allow(rustc::potential_query_instability)]
-        for region in liveness_constraints.live_regions_unordered() {
-            self.typeck.constraints.liveness_constraints.add_location(region, location);
-        }
-    }
-}
-
 /// The MIR type checker. Visits the MIR and enforces all the
 /// constraints needed for it to be valid and well-typed. Along the
 /// way, it accrues region constraints -- these can later be used by
@@ -584,6 +217,9 @@ struct TypeChecker<'a, 'tcx> {
     infcx: &'a BorrowckInferCtxt<'tcx>,
     last_span: Span,
     body: &'a Body<'tcx>,
+    /// The bodies of all promoteds. As promoteds have a completely separate CFG
+    /// recursing into them may corrupt your data structures if you're not careful.
+    promoted: &'a IndexSlice<Promoted, Body<'tcx>>,
     /// User type annotations are shared between the main MIR and the MIR of
     /// all of the promoted items.
     user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
@@ -732,6 +368,10 @@ impl Locations {
 }
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
     fn body(&self) -> &Body<'tcx> {
         self.body
     }
@@ -859,6 +499,62 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         Ok(())
     }
 
+    fn check_promoted(&mut self, promoted_body: &'a Body<'tcx>, location: Location) {
+        // Determine the constraints from the promoted MIR by running the type
+        // checker on the promoted MIR, then transfer the constraints back to
+        // the main MIR, changing the locations to the provided location.
+
+        let parent_body = mem::replace(&mut self.body, promoted_body);
+
+        // Use new sets of constraints and closure bounds so that we can
+        // modify their locations.
+        let polonius_facts = &mut None;
+        let mut constraints = Default::default();
+        let mut liveness_constraints =
+            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
+
+        // Don't try to add borrow_region facts for the promoted MIR as they refer
+        // to the wrong locations.
+        let mut swap_constraints = |this: &mut Self| {
+            mem::swap(this.polonius_facts, polonius_facts);
+            mem::swap(&mut this.constraints.outlives_constraints, &mut constraints);
+            mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints);
+        };
+
+        swap_constraints(self);
+
+        self.visit_body(promoted_body);
+
+        self.body = parent_body;
+
+        // Merge the outlives constraints back in, at the given location.
+        swap_constraints(self);
+        let locations = location.to_locations();
+        for constraint in constraints.outlives().iter() {
+            let mut constraint = *constraint;
+            constraint.locations = locations;
+            if let ConstraintCategory::Return(_)
+            | ConstraintCategory::UseAsConst
+            | ConstraintCategory::UseAsStatic = constraint.category
+            {
+                // "Returning" from a promoted is an assignment to a
+                // temporary from the user's point of view.
+                constraint.category = ConstraintCategory::Boring;
+            }
+            self.constraints.outlives_constraints.push(constraint)
+        }
+        // If the region is live at least one location in the promoted MIR,
+        // then add a liveness constraint to the main MIR for this region
+        // at the location provided as an argument to this method
+        //
+        // add_location doesn't care about ordering so not a problem for the live regions to be
+        // unordered.
+        #[allow(rustc::potential_query_instability)]
+        for region in liveness_constraints.live_regions_unordered() {
+            self.constraints.liveness_constraints.add_location(region, location);
+        }
+    }
+
     fn check_inline_const(
         &mut self,
         inferred_ty: Ty<'tcx>,
@@ -888,15 +584,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Locations::All(span),
         );
     }
+}
 
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
+impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
+    fn visit_span(&mut self, span: Span) {
+        if !span.is_dummy() {
+            debug!(?span);
+            self.last_span = span;
+        }
+    }
+
+    #[instrument(skip(self, body), level = "debug")]
+    fn visit_body(&mut self, body: &Body<'tcx>) {
+        debug_assert!(std::ptr::eq(self.body, body));
+
+        for (local, local_decl) in body.local_decls.iter_enumerated() {
+            self.visit_local_decl(local, local_decl);
+        }
+
+        for (block, block_data) in body.basic_blocks.iter_enumerated() {
+            let mut location = Location { block, statement_index: 0 };
+            for stmt in &block_data.statements {
+                self.visit_statement(stmt, location);
+                location.statement_index += 1;
+            }
+
+            self.visit_terminator(block_data.terminator(), location);
+            self.check_iscleanup(block_data);
+        }
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn check_stmt(&mut self, stmt: &Statement<'tcx>, location: Location) {
+    fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
+        self.super_statement(stmt, location);
         let tcx = self.tcx();
-        debug!("stmt kind: {:?}", stmt.kind);
         match &stmt.kind {
             StatementKind::Assign(box (place, rv)) => {
                 // Assignments to temporaries are not "interesting";
@@ -976,7 +697,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
                 }
 
-                self.check_rvalue(rv, location);
                 if !self.unsized_feature_enabled() {
                     let trait_ref = ty::TraitRef::new(
                         tcx,
@@ -1011,14 +731,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            StatementKind::Intrinsic(box kind) => match kind {
-                NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
-                NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
-                    stmt.source_info.span,
-                    "Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
-                ),
-            },
-            StatementKind::FakeRead(..)
+            StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
+            | StatementKind::FakeRead(..)
             | StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
             | StatementKind::Retag { .. }
@@ -1027,14 +741,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | StatementKind::PlaceMention(..)
             | StatementKind::BackwardIncompatibleDropHint { .. }
             | StatementKind::Nop => {}
-            StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
+            StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
+            | StatementKind::Deinit(..)
+            | StatementKind::SetDiscriminant { .. } => {
                 bug!("Statement not allowed in this MIR phase")
             }
         }
     }
 
-    #[instrument(skip(self, term_location), level = "debug")]
-    fn check_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
+    #[instrument(skip(self), level = "debug")]
+    fn visit_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
+        self.super_terminator(term, term_location);
         let tcx = self.tcx();
         debug!("terminator kind: {:?}", term.kind);
         match &term.kind {
@@ -1052,8 +769,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             TerminatorKind::SwitchInt { discr, .. } => {
-                self.check_operand(discr, term_location);
-
                 let switch_ty = discr.ty(self.body, tcx);
                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
@@ -1068,11 +783,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     _ => unreachable!(),
                 };
 
-                self.check_operand(func, term_location);
-                for arg in args {
-                    self.check_operand(&arg.node, term_location);
-                }
-
                 let func_ty = func.ty(self.body, tcx);
                 debug!("func_ty.kind: {:?}", func_ty.kind());
 
@@ -1159,8 +869,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.check_call_inputs(term, func, &sig, args, term_location, call_source);
             }
             TerminatorKind::Assert { cond, msg, .. } => {
-                self.check_operand(cond, term_location);
-
                 let cond_ty = cond.ty(self.body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
@@ -1176,8 +884,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
             TerminatorKind::Yield { value, resume_arg, .. } => {
-                self.check_operand(value, term_location);
-
                 match self.body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-coroutine"),
                     Some(ty) => {
@@ -1225,385 +931,75 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    fn check_call_dest(
-        &mut self,
-        term: &Terminator<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        destination: Place<'tcx>,
-        target: Option<BasicBlock>,
-        term_location: Location,
-    ) {
-        let tcx = self.tcx();
-        match target {
-            Some(_) => {
-                let dest_ty = destination.ty(self.body, tcx).ty;
-                let dest_ty = self.normalize(dest_ty, term_location);
-                let category = match destination.as_local() {
-                    Some(RETURN_PLACE) => {
-                        if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
-                            self.universal_regions.defining_ty
-                        {
-                            if tcx.is_static(def_id) {
-                                ConstraintCategory::UseAsStatic
-                            } else {
-                                ConstraintCategory::UseAsConst
-                            }
-                        } else {
-                            ConstraintCategory::Return(ReturnConstraint::Normal)
-                        }
-                    }
-                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
-                        ConstraintCategory::Boring
-                    }
-                    // The return type of a call is interesting for diagnostics.
-                    _ => ConstraintCategory::Assignment,
-                };
-
-                let locations = term_location.to_locations();
-
-                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
-                    span_mirbug!(
-                        self,
-                        term,
-                        "call dest mismatch ({:?} <- {:?}): {:?}",
-                        dest_ty,
-                        sig.output(),
-                        terr
-                    );
-                }
-
-                // When `unsized_fn_params` and `unsized_locals` are both not enabled,
-                // this check is done at `check_local`.
-                if self.unsized_feature_enabled() {
-                    let span = term.source_info.span;
-                    self.ensure_place_sized(dest_ty, span);
-                }
-            }
-            None => {
-                // The signature in this call can reference region variables,
-                // so erase them before calling a query.
-                let output_ty = self.tcx().erase_regions(sig.output());
-                if !output_ty.is_privately_uninhabited(
-                    self.tcx(),
-                    self.infcx.typing_env(self.infcx.param_env),
-                ) {
-                    span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
-                }
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
-    fn check_call_inputs(
-        &mut self,
-        term: &Terminator<'tcx>,
-        func: &Operand<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        args: &[Spanned<Operand<'tcx>>],
-        term_location: Location,
-        call_source: CallSource,
-    ) {
-        if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
-            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
-        }
-
-        let func_ty = func.ty(self.body, self.infcx.tcx);
-        if let ty::FnDef(def_id, _) = *func_ty.kind() {
-            // Some of the SIMD intrinsics are special: they need a particular argument to be a
-            // constant. (Eventually this should use const-generics, but those are not up for the
-            // task yet: https://github.com/rust-lang/rust/issues/85229.)
-            if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
-                self.tcx().intrinsic(def_id).map(|i| i.name)
-            {
-                let idx = match name {
-                    sym::simd_shuffle => 2,
-                    _ => 1,
-                };
-                if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
-                    self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
-                        span: term.source_info.span,
-                        arg: idx + 1,
-                        intrinsic: name.to_string(),
-                    });
-                }
-            }
-        }
-        debug!(?func_ty);
+    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+        self.super_local_decl(local, local_decl);
 
-        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
-            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
+        for user_ty in
+            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
+        {
+            let span = self.user_type_annotations[user_ty.base].span;
 
-            let op_arg_ty = self.normalize(op_arg_ty, term_location);
-            let category = if call_source.from_hir_call() {
-                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
+            let ty = if local_decl.is_nonref_binding() {
+                local_decl.ty
+            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
+                // If we have a binding of the form `let ref x: T = ..`
+                // then remove the outermost reference so we can check the
+                // type annotation for the remaining type.
+                rty
             } else {
-                ConstraintCategory::Boring
+                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
             };
-            if let Err(terr) =
-                self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
-            {
+
+            if let Err(terr) = self.relate_type_and_user_type(
+                ty,
+                ty::Invariant,
+                user_ty,
+                Locations::All(span),
+                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
+            ) {
                 span_mirbug!(
                     self,
-                    term,
-                    "bad arg #{:?} ({:?} <- {:?}): {:?}",
-                    n,
-                    fn_arg,
-                    op_arg_ty,
-                    terr
+                    local,
+                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
+                    local,
+                    local_decl.ty,
+                    local_decl.user_ty,
+                    terr,
                 );
             }
         }
-    }
-
-    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
-        let is_cleanup = block_data.is_cleanup;
-        self.last_span = block_data.terminator().source_info.span;
-        match block_data.terminator().kind {
-            TerminatorKind::Goto { target } => {
-                self.assert_iscleanup(block_data, target, is_cleanup)
-            }
-            TerminatorKind::SwitchInt { ref targets, .. } => {
-                for target in targets.all_targets() {
-                    self.assert_iscleanup(block_data, *target, is_cleanup);
-                }
-            }
-            TerminatorKind::UnwindResume => {
-                if !is_cleanup {
-                    span_mirbug!(self, block_data, "resume on non-cleanup block!")
-                }
-            }
-            TerminatorKind::UnwindTerminate(_) => {
-                if !is_cleanup {
-                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
-                }
-            }
-            TerminatorKind::Return => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "return on cleanup block")
-                }
-            }
-            TerminatorKind::TailCall { .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "tailcall on cleanup block")
-                }
-            }
-            TerminatorKind::CoroutineDrop { .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
-                }
-            }
-            TerminatorKind::Yield { resume, drop, .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "yield in cleanup block")
-                }
-                self.assert_iscleanup(block_data, resume, is_cleanup);
-                if let Some(drop) = drop {
-                    self.assert_iscleanup(block_data, drop, is_cleanup);
-                }
-            }
-            TerminatorKind::Unreachable => {}
-            TerminatorKind::Drop { target, unwind, .. }
-            | TerminatorKind::Assert { target, unwind, .. } => {
-                self.assert_iscleanup(block_data, target, is_cleanup);
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::Call { ref target, unwind, .. } => {
-                if let &Some(target) = target {
-                    self.assert_iscleanup(block_data, target, is_cleanup);
-                }
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
-                self.assert_iscleanup(block_data, real_target, is_cleanup);
-                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
-            }
-            TerminatorKind::FalseUnwind { real_target, unwind } => {
-                self.assert_iscleanup(block_data, real_target, is_cleanup);
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
-                for &target in targets {
-                    self.assert_iscleanup(block_data, target, is_cleanup);
-                }
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-        }
-    }
-
-    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
-        if self.body[bb].is_cleanup != iscleanuppad {
-            span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
-        }
-    }
-
-    fn assert_iscleanup_unwind(
-        &mut self,
-        ctxt: &dyn fmt::Debug,
-        unwind: UnwindAction,
-        is_cleanup: bool,
-    ) {
-        match unwind {
-            UnwindAction::Cleanup(unwind) => {
-                if is_cleanup {
-                    span_mirbug!(self, ctxt, "unwind on cleanup block")
-                }
-                self.assert_iscleanup(ctxt, unwind, true);
-            }
-            UnwindAction::Continue => {
-                if is_cleanup {
-                    span_mirbug!(self, ctxt, "unwind on cleanup block")
-                }
-            }
-            UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
-        }
-    }
-
-    fn check_local(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        match self.body.local_kind(local) {
-            LocalKind::ReturnPointer | LocalKind::Arg => {
-                // return values of normal functions are required to be
-                // sized by typeck, but return values of ADT constructors are
-                // not because we don't include a `Self: Sized` bounds on them.
-                //
-                // Unbound parts of arguments were never required to be Sized
-                // - maybe we should make that a warning.
-                return;
-            }
-            LocalKind::Temp => {}
-        }
 
         // When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
         // and nullary ops are checked in `check_call_dest`.
         if !self.unsized_feature_enabled() {
-            let span = local_decl.source_info.span;
-            let ty = local_decl.ty;
-            self.ensure_place_sized(ty, span);
-        }
-    }
-
-    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
-        let tcx = self.tcx();
-
-        // Erase the regions from `ty` to get a global type. The
-        // `Sized` bound in no way depends on precise regions, so this
-        // shouldn't affect `is_sized`.
-        let erased_ty = tcx.erase_regions(ty);
-        // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
-        if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
-            // in current MIR construction, all non-control-flow rvalue
-            // expressions evaluate through `as_temp` or `into` a return
-            // slot or local, so to find all unsized rvalues it is enough
-            // to check all temps, return slots and locals.
-            if self.reported_errors.replace((ty, span)).is_none() {
-                // While this is located in `nll::typeck` this error is not
-                // an NLL error, it's a required check to prevent creation
-                // of unsized rvalues in a call expression.
-                self.tcx().dcx().emit_err(MoveUnsized { ty, span });
-            }
-        }
-    }
-
-    fn aggregate_field_ty(
-        &mut self,
-        ak: &AggregateKind<'tcx>,
-        field_index: FieldIdx,
-        location: Location,
-    ) -> Result<Ty<'tcx>, FieldAccessError> {
-        let tcx = self.tcx();
-
-        match *ak {
-            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
-                let def = tcx.adt_def(adt_did);
-                let variant = &def.variant(variant_index);
-                let adj_field_index = active_field_index.unwrap_or(field_index);
-                if let Some(field) = variant.fields.get(adj_field_index) {
-                    Ok(self.normalize(field.ty(tcx, args), location))
-                } else {
-                    Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
+            match self.body.local_kind(local) {
+                LocalKind::ReturnPointer | LocalKind::Arg => {
+                    // return values of normal functions are required to be
+                    // sized by typeck, but return values of ADT constructors are
+                    // not because we don't include a `Self: Sized` bounds on them.
+                    //
+                    // Unbound parts of arguments were never required to be Sized
+                    // - maybe we should make that a warning.
+                    return;
                 }
-            }
-            AggregateKind::Closure(_, args) => {
-                match args.as_closure().upvar_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_closure().upvar_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::Coroutine(_, args) => {
-                // It doesn't make sense to look at a field beyond the prefix;
-                // these require a variant index, and are not initialized in
-                // aggregate rvalues.
-                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_coroutine().prefix_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::CoroutineClosure(_, args) => {
-                match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_coroutine_closure().upvar_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::Array(ty) => Ok(ty),
-            AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
-                unreachable!("This should have been covered in check_rvalues");
-            }
-        }
-    }
-
-    fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
-        debug!(?op, ?location, "check_operand");
-
-        if let Operand::Constant(constant) = op {
-            let maybe_uneval = match constant.const_ {
-                Const::Val(..) | Const::Ty(_, _) => None,
-                Const::Unevaluated(uv, _) => Some(uv),
-            };
-
-            if let Some(uv) = maybe_uneval {
-                if uv.promoted.is_none() {
-                    let tcx = self.tcx();
-                    let def_id = uv.def;
-                    if tcx.def_kind(def_id) == DefKind::InlineConst {
-                        let def_id = def_id.expect_local();
-                        let predicates = self.prove_closure_bounds(
-                            tcx,
-                            def_id,
-                            uv.args,
-                            location.to_locations(),
-                        );
-                        self.normalize_and_prove_instantiated_predicates(
-                            def_id.to_def_id(),
-                            predicates,
-                            location.to_locations(),
-                        );
-                    }
+                LocalKind::Temp => {
+                    let span = local_decl.source_info.span;
+                    let ty = local_decl.ty;
+                    self.ensure_place_sized(ty, span);
                 }
             }
         }
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
         let tcx = self.tcx();
         let span = self.body.source_info(location).span;
-
         match rvalue {
-            Rvalue::Aggregate(ak, ops) => {
-                for op in ops {
-                    self.check_operand(op, location);
-                }
-                self.check_aggregate_rvalue(rvalue, ak, ops, location)
-            }
+            Rvalue::Aggregate(ak, ops) => self.check_aggregate_rvalue(rvalue, ak, ops, location),
 
             Rvalue::Repeat(operand, len) => {
-                self.check_operand(operand, location);
-
                 let array_ty = rvalue.ty(self.body.local_decls(), tcx);
                 self.prove_predicate(
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
@@ -1656,9 +1052,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
             &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
 
-            Rvalue::ShallowInitBox(operand, ty) => {
-                self.check_operand(operand, location);
-
+            Rvalue::ShallowInitBox(_operand, ty) => {
                 let trait_ref = ty::TraitRef::new(
                     tcx,
                     tcx.require_lang_item(LangItem::Sized, Some(span)),
@@ -1673,8 +1067,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             Rvalue::Cast(cast_kind, op, ty) => {
-                self.check_operand(op, location);
-
                 match *cast_kind {
                     CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
@@ -2191,9 +1583,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
                 box (left, right),
             ) => {
-                self.check_operand(left, location);
-                self.check_operand(right, location);
-
                 let ty_left = left.ty(self.body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
@@ -2242,23 +1631,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
 
-            Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
-                self.check_operand(operand, location);
-            }
-            Rvalue::CopyForDeref(place) => {
-                let op = &Operand::Copy(*place);
-                self.check_operand(op, location);
-            }
-
-            Rvalue::BinaryOp(_, box (left, right)) => {
-                self.check_operand(left, location);
-                self.check_operand(right, location);
-            }
-
             Rvalue::WrapUnsafeBinder(op, ty) => {
-                self.check_operand(op, location);
                 let operand_ty = op.ty(self.body, self.tcx());
-
                 let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
                     unreachable!();
                 };
@@ -2276,7 +1650,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 .unwrap();
             }
 
-            Rvalue::RawPtr(..)
+            Rvalue::Use(_)
+            | Rvalue::UnaryOp(_, _)
+            | Rvalue::CopyForDeref(_)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::RawPtr(..)
             | Rvalue::ThreadLocalRef(..)
             | Rvalue::Len(..)
             | Rvalue::Discriminant(..)
@@ -2284,6 +1662,543 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        self.super_operand(op, location);
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.const_ {
+                Const::Val(..) | Const::Ty(_, _) => None,
+                Const::Unevaluated(uv, _) => Some(uv),
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let tcx = self.tcx();
+                    let def_id = uv.def;
+                    if tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let def_id = def_id.expect_local();
+                        let predicates = self.prove_closure_bounds(
+                            tcx,
+                            def_id,
+                            uv.args,
+                            location.to_locations(),
+                        );
+                        self.normalize_and_prove_instantiated_predicates(
+                            def_id.to_def_id(),
+                            predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
+        self.super_const_operand(constant, location);
+        let ty = constant.const_.ty();
+
+        self.infcx.tcx.for_each_free_region(&ty, |live_region| {
+            let live_region_vid = self.universal_regions.to_region_vid(live_region);
+            self.constraints.liveness_constraints.add_location(live_region_vid, location);
+        });
+
+        let locations = location.to_locations();
+        if let Some(annotation_index) = constant.user_ty {
+            if let Err(terr) = self.relate_type_and_user_type(
+                constant.const_.ty(),
+                ty::Invariant,
+                &UserTypeProjection { base: annotation_index, projs: vec![] },
+                locations,
+                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
+            ) {
+                let annotation = &self.user_type_annotations[annotation_index];
+                span_mirbug!(
+                    self,
+                    constant,
+                    "bad constant user type {:?} vs {:?}: {:?}",
+                    annotation,
+                    constant.const_.ty(),
+                    terr,
+                );
+            }
+        } else {
+            let tcx = self.tcx();
+            let maybe_uneval = match constant.const_ {
+                Const::Ty(_, ct) => match ct.kind() {
+                    ty::ConstKind::Unevaluated(uv) => {
+                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
+                    }
+                    _ => None,
+                },
+                Const::Unevaluated(uv, _) => Some(uv),
+                _ => None,
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if let Some(promoted) = uv.promoted {
+                    let promoted_body = &self.promoted[promoted];
+                    self.check_promoted(promoted_body, location);
+                    let promoted_ty = promoted_body.return_ty();
+                    if let Err(terr) =
+                        self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
+                    {
+                        span_mirbug!(
+                            self,
+                            promoted,
+                            "bad promoted type ({:?}: {:?}): {:?}",
+                            ty,
+                            promoted_ty,
+                            terr
+                        );
+                    };
+                } else {
+                    self.ascribe_user_type(
+                        constant.const_.ty(),
+                        ty::UserType::new(ty::UserTypeKind::TypeOf(
+                            uv.def,
+                            UserArgs { args: uv.args, user_self_ty: None },
+                        )),
+                        locations.span(self.body),
+                    );
+                }
+            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
+                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
+                let normalized_ty = self.normalize(unnormalized_ty, locations);
+                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
+
+                if let Err(terr) =
+                    self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
+                {
+                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
+                }
+            }
+
+            if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
+                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
+                self.normalize_and_prove_instantiated_predicates(
+                    def_id,
+                    instantiated_predicates,
+                    locations,
+                );
+
+                assert!(!matches!(
+                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
+                    Some(DefKind::Impl { of_trait: true })
+                ));
+                self.prove_predicates(
+                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
+                    locations,
+                    ConstraintCategory::Boring,
+                );
+            }
+        }
+    }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        self.super_place(place, context, location);
+        let tcx = self.tcx();
+        let place_ty = place.ty(self.body, tcx);
+        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+            let trait_ref = ty::TraitRef::new(
+                tcx,
+                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
+                [place_ty.ty],
+            );
+
+            // To have a `Copy` operand, the type `T` of the
+            // value must be `Copy`. Note that we prove that `T: Copy`,
+            // rather than using the `is_copy_modulo_regions`
+            // test. This is important because
+            // `is_copy_modulo_regions` ignores the resulting region
+            // obligations and assumes they pass. This can result in
+            // bounds from `Copy` impls being unsoundly ignored (e.g.,
+            // #29149). Note that we decide to use `Copy` before knowing
+            // whether the bounds fully apply: in effect, the rule is
+            // that if a value of some type could implement `Copy`, then
+            // it must.
+            self.prove_trait_ref(trait_ref, location.to_locations(), ConstraintCategory::CopyBound);
+        }
+    }
+
+    fn visit_projection_elem(
+        &mut self,
+        place: PlaceRef<'tcx>,
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        let tcx = self.tcx();
+        let base_ty = place.ty(self.body(), tcx);
+        match elem {
+            // All these projections don't add any constraints, so there's nothing to
+            // do here. We check their invariants in the MIR validator after all.
+            ProjectionElem::Deref
+            | ProjectionElem::Index(_)
+            | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Downcast(..) => {}
+            ProjectionElem::Field(field, fty) => {
+                let fty = self.normalize(fty, location);
+                let ty = base_ty.field_ty(tcx, field);
+                let ty = self.normalize(ty, location);
+                debug!(?fty, ?ty);
+
+                if let Err(terr) = self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    fty,
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                ) {
+                    span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
+                }
+            }
+            ProjectionElem::OpaqueCast(ty) => {
+                let ty = self.normalize(ty, location);
+                self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    base_ty.ty,
+                    location.to_locations(),
+                    ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
+                )
+                .unwrap();
+            }
+            ProjectionElem::UnwrapUnsafeBinder(ty) => {
+                let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
+                    unreachable!();
+                };
+                let found_ty = self.infcx.instantiate_binder_with_fresh_vars(
+                    self.body.source_info(location).span,
+                    BoundRegionConversionTime::HigherRankedType,
+                    binder_ty.into(),
+                );
+                self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    found_ty,
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                )
+                .unwrap();
+            }
+            ProjectionElem::Subtype(_) => {
+                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    fn check_call_dest(
+        &mut self,
+        term: &Terminator<'tcx>,
+        sig: &ty::FnSig<'tcx>,
+        destination: Place<'tcx>,
+        target: Option<BasicBlock>,
+        term_location: Location,
+    ) {
+        let tcx = self.tcx();
+        match target {
+            Some(_) => {
+                let dest_ty = destination.ty(self.body, tcx).ty;
+                let dest_ty = self.normalize(dest_ty, term_location);
+                let category = match destination.as_local() {
+                    Some(RETURN_PLACE) => {
+                        if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
+                            self.universal_regions.defining_ty
+                        {
+                            if tcx.is_static(def_id) {
+                                ConstraintCategory::UseAsStatic
+                            } else {
+                                ConstraintCategory::UseAsConst
+                            }
+                        } else {
+                            ConstraintCategory::Return(ReturnConstraint::Normal)
+                        }
+                    }
+                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
+                        ConstraintCategory::Boring
+                    }
+                    // The return type of a call is interesting for diagnostics.
+                    _ => ConstraintCategory::Assignment,
+                };
+
+                let locations = term_location.to_locations();
+
+                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
+                    span_mirbug!(
+                        self,
+                        term,
+                        "call dest mismatch ({:?} <- {:?}): {:?}",
+                        dest_ty,
+                        sig.output(),
+                        terr
+                    );
+                }
+
+                // When `unsized_fn_params` and `unsized_locals` are both not enabled,
+                // this check is done at `check_local`.
+                if self.unsized_feature_enabled() {
+                    let span = term.source_info.span;
+                    self.ensure_place_sized(dest_ty, span);
+                }
+            }
+            None => {
+                // The signature in this call can reference region variables,
+                // so erase them before calling a query.
+                let output_ty = self.tcx().erase_regions(sig.output());
+                if !output_ty.is_privately_uninhabited(
+                    self.tcx(),
+                    self.infcx.typing_env(self.infcx.param_env),
+                ) {
+                    span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
+                }
+            }
+        }
+    }
+
+    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
+    fn check_call_inputs(
+        &mut self,
+        term: &Terminator<'tcx>,
+        func: &Operand<'tcx>,
+        sig: &ty::FnSig<'tcx>,
+        args: &[Spanned<Operand<'tcx>>],
+        term_location: Location,
+        call_source: CallSource,
+    ) {
+        if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
+            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
+        }
+
+        let func_ty = func.ty(self.body, self.infcx.tcx);
+        if let ty::FnDef(def_id, _) = *func_ty.kind() {
+            // Some of the SIMD intrinsics are special: they need a particular argument to be a
+            // constant. (Eventually this should use const-generics, but those are not up for the
+            // task yet: https://github.com/rust-lang/rust/issues/85229.)
+            if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
+                self.tcx().intrinsic(def_id).map(|i| i.name)
+            {
+                let idx = match name {
+                    sym::simd_shuffle => 2,
+                    _ => 1,
+                };
+                if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
+                    self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
+                        span: term.source_info.span,
+                        arg: idx + 1,
+                        intrinsic: name.to_string(),
+                    });
+                }
+            }
+        }
+        debug!(?func_ty);
+
+        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
+            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
+
+            let op_arg_ty = self.normalize(op_arg_ty, term_location);
+            let category = if call_source.from_hir_call() {
+                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
+            } else {
+                ConstraintCategory::Boring
+            };
+            if let Err(terr) =
+                self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
+            {
+                span_mirbug!(
+                    self,
+                    term,
+                    "bad arg #{:?} ({:?} <- {:?}): {:?}",
+                    n,
+                    fn_arg,
+                    op_arg_ty,
+                    terr
+                );
+            }
+        }
+    }
+
+    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
+        let is_cleanup = block_data.is_cleanup;
+        match block_data.terminator().kind {
+            TerminatorKind::Goto { target } => {
+                self.assert_iscleanup(block_data, target, is_cleanup)
+            }
+            TerminatorKind::SwitchInt { ref targets, .. } => {
+                for target in targets.all_targets() {
+                    self.assert_iscleanup(block_data, *target, is_cleanup);
+                }
+            }
+            TerminatorKind::UnwindResume => {
+                if !is_cleanup {
+                    span_mirbug!(self, block_data, "resume on non-cleanup block!")
+                }
+            }
+            TerminatorKind::UnwindTerminate(_) => {
+                if !is_cleanup {
+                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
+                }
+            }
+            TerminatorKind::Return => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "return on cleanup block")
+                }
+            }
+            TerminatorKind::TailCall { .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "tailcall on cleanup block")
+                }
+            }
+            TerminatorKind::CoroutineDrop { .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
+                }
+            }
+            TerminatorKind::Yield { resume, drop, .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "yield in cleanup block")
+                }
+                self.assert_iscleanup(block_data, resume, is_cleanup);
+                if let Some(drop) = drop {
+                    self.assert_iscleanup(block_data, drop, is_cleanup);
+                }
+            }
+            TerminatorKind::Unreachable => {}
+            TerminatorKind::Drop { target, unwind, .. }
+            | TerminatorKind::Assert { target, unwind, .. } => {
+                self.assert_iscleanup(block_data, target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::Call { ref target, unwind, .. } => {
+                if let &Some(target) = target {
+                    self.assert_iscleanup(block_data, target, is_cleanup);
+                }
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
+            }
+            TerminatorKind::FalseUnwind { real_target, unwind } => {
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
+                for &target in targets {
+                    self.assert_iscleanup(block_data, target, is_cleanup);
+                }
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+        }
+    }
+
+    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
+        if self.body[bb].is_cleanup != iscleanuppad {
+            span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
+        }
+    }
+
+    fn assert_iscleanup_unwind(
+        &mut self,
+        ctxt: &dyn fmt::Debug,
+        unwind: UnwindAction,
+        is_cleanup: bool,
+    ) {
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+                self.assert_iscleanup(ctxt, unwind, true);
+            }
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
+        }
+    }
+
+    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
+        let tcx = self.tcx();
+
+        // Erase the regions from `ty` to get a global type. The
+        // `Sized` bound in no way depends on precise regions, so this
+        // shouldn't affect `is_sized`.
+        let erased_ty = tcx.erase_regions(ty);
+        // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
+        if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
+            // in current MIR construction, all non-control-flow rvalue
+            // expressions evaluate through `as_temp` or `into` a return
+            // slot or local, so to find all unsized rvalues it is enough
+            // to check all temps, return slots and locals.
+            if self.reported_errors.replace((ty, span)).is_none() {
+                // While this is located in `nll::typeck` this error is not
+                // an NLL error, it's a required check to prevent creation
+                // of unsized rvalues in a call expression.
+                self.tcx().dcx().emit_err(MoveUnsized { ty, span });
+            }
+        }
+    }
+
+    fn aggregate_field_ty(
+        &mut self,
+        ak: &AggregateKind<'tcx>,
+        field_index: FieldIdx,
+        location: Location,
+    ) -> Result<Ty<'tcx>, FieldAccessError> {
+        let tcx = self.tcx();
+
+        match *ak {
+            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
+                let def = tcx.adt_def(adt_did);
+                let variant = &def.variant(variant_index);
+                let adj_field_index = active_field_index.unwrap_or(field_index);
+                if let Some(field) = variant.fields.get(adj_field_index) {
+                    Ok(self.normalize(field.ty(tcx, args), location))
+                } else {
+                    Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
+                }
+            }
+            AggregateKind::Closure(_, args) => {
+                match args.as_closure().upvar_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_closure().upvar_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::Coroutine(_, args) => {
+                // It doesn't make sense to look at a field beyond the prefix;
+                // these require a variant index, and are not initialized in
+                // aggregate rvalues.
+                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_coroutine().prefix_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::CoroutineClosure(_, args) => {
+                match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_coroutine_closure().upvar_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::Array(ty) => Ok(ty),
+            AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
+                unreachable!("This should have been covered in check_rvalues");
+            }
+        }
+    }
+
     /// If this rvalue supports a user-given type annotation, then
     /// extract and return it. This represents the final type of the
     /// rvalue and will be unified with the inferred type.
@@ -2623,30 +2538,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         tcx.predicates_of(def_id).instantiate(tcx, args)
     }
-
-    #[instrument(skip(self), level = "debug")]
-    fn typeck_mir(&mut self) {
-        self.last_span = self.body.span;
-        debug!(?self.body.span);
-
-        for (local, local_decl) in self.body.local_decls.iter_enumerated() {
-            self.check_local(local, local_decl);
-        }
-
-        for (block, block_data) in self.body.basic_blocks.iter_enumerated() {
-            let mut location = Location { block, statement_index: 0 };
-            for stmt in &block_data.statements {
-                if !stmt.source_info.span.is_dummy() {
-                    self.last_span = stmt.source_info.span;
-                }
-                self.check_stmt(stmt, location);
-                location.statement_index += 1;
-            }
-
-            self.check_terminator(block_data.terminator(), location);
-            self.check_iscleanup(block_data);
-        }
-    }
 }
 
 trait NormalizeLocation: fmt::Debug + Copy {
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 53c61831b42..5788966b6e7 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -140,8 +140,9 @@ impl CfgEval<'_> {
                     Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
                 }
                 Annotatable::Stmt(_) => {
-                    let stmt =
-                        parser.parse_stmt_without_recovery(false, ForceCollect::Yes)?.unwrap();
+                    let stmt = parser
+                        .parse_stmt_without_recovery(false, ForceCollect::Yes, false)?
+                        .unwrap();
                     Annotatable::Stmt(P(self.flat_map_stmt(stmt).pop().unwrap()))
                 }
                 Annotatable::Expr(_) => {
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c5d2a84fba4..dab3053d8b0 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,6 +5,7 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -18,7 +19,6 @@
 #![feature(rustdoc_internals)]
 #![feature(string_from_utf8_lossy_owned)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate proc_macro;
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 72c9df59d83..6e345b2a6fd 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -624,25 +624,25 @@ pub mod intrinsics {
     #[rustc_intrinsic]
     pub fn size_of<T>() -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize;
+    pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
     #[rustc_intrinsic]
     pub fn min_align_of<T>() -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize;
+    pub unsafe fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize);
+    pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
     #[rustc_intrinsic]
-    pub unsafe fn transmute<T, U>(_e: T) -> U;
+    pub unsafe fn transmute<T, U>(e: T) -> U;
     #[rustc_intrinsic]
-    pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
+    pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
     #[rustc_intrinsic]
     pub fn needs_drop<T: ?::Sized>() -> bool;
     #[rustc_intrinsic]
-    pub fn bitreverse<T>(_x: T) -> T;
+    pub fn bitreverse<T>(x: T) -> T;
     #[rustc_intrinsic]
-    pub fn bswap<T>(_x: T) -> T;
+    pub fn bswap<T>(x: T) -> T;
     #[rustc_intrinsic]
-    pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize);
+    pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
     #[rustc_intrinsic]
     pub unsafe fn unreachable() -> !;
 }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 6735ae024d1..75f3a3c1972 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1031,7 +1031,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1052,7 +1052,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1073,7 +1073,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1094,7 +1094,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 3dad35bc4ce..5544aee9eaf 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -595,25 +595,25 @@ pub mod intrinsics {
     #[rustc_intrinsic]
     pub fn size_of<T>() -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize;
+    pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
     #[rustc_intrinsic]
     pub fn min_align_of<T>() -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize;
+    pub unsafe fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
     #[rustc_intrinsic]
-    pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize);
+    pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
     #[rustc_intrinsic]
-    pub unsafe fn transmute<T, U>(_e: T) -> U;
+    pub unsafe fn transmute<T, U>(e: T) -> U;
     #[rustc_intrinsic]
-    pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
+    pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
     #[rustc_intrinsic]
     pub fn needs_drop<T: ?::Sized>() -> bool;
     #[rustc_intrinsic]
-    pub fn bitreverse<T>(_x: T) -> T;
+    pub fn bitreverse<T>(x: T) -> T;
     #[rustc_intrinsic]
-    pub fn bswap<T>(_x: T) -> T;
+    pub fn bswap<T>(x: T) -> T;
     #[rustc_intrinsic]
-    pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize);
+    pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
     #[rustc_intrinsic]
     pub unsafe fn unreachable() -> !;
 }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index dec93bbccc3..f622646a5d9 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -19,7 +19,6 @@
 #![feature(rustdoc_internals)]
 #![feature(slice_as_array)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::any::Any;
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 32f689608f8..3710625ac12 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -63,7 +63,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr
             },
         };
 
-        for attr in tcx.hir().attrs(rustc_hir::CRATE_HIR_ID) {
+        for attr in tcx.hir_attrs(rustc_hir::CRATE_HIR_ID) {
             ams.check_attr(attr);
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs
index 63023fdba20..383d0579e52 100644
--- a/compiler/rustc_codegen_ssa/src/back/command.rs
+++ b/compiler/rustc_codegen_ssa/src/back/command.rs
@@ -143,13 +143,6 @@ impl Command {
             return false;
         }
 
-        // Right now LLD doesn't support the `@` syntax of passing an argument
-        // through files, so regardless of the platform we try to go to the OS
-        // on this one.
-        if let Program::Lld(..) = self.program {
-            return false;
-        }
-
         // Ok so on Windows to spawn a process is 32,768 characters in its
         // command line [1]. Unfortunately we don't actually have access to that
         // as it's calculated just before spawning. Instead we perform a
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 7d9971c021d..ea961f222db 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -22,7 +22,9 @@ use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_macros::LintDiagnostic;
 use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
-use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
+use rustc_metadata::{
+    NativeLibSearchFallback, find_native_static_library, walk_native_lib_search_dirs,
+};
 use rustc_middle::bug;
 use rustc_middle::lint::lint_level;
 use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
@@ -1286,8 +1288,7 @@ fn link_sanitizer_runtime(
         if path.exists() {
             sess.target_tlib_path.dir.clone()
         } else {
-            let default_sysroot =
-                filesearch::get_or_default_sysroot().expect("Failed finding sysroot");
+            let default_sysroot = filesearch::get_or_default_sysroot();
             let default_tlib =
                 filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.tuple());
             default_tlib
@@ -2129,19 +2130,15 @@ fn add_library_search_dirs(
         return;
     }
 
-    walk_native_lib_search_dirs(
-        sess,
-        self_contained_components,
-        apple_sdk_root,
-        |dir, is_framework| {
-            if is_framework {
-                cmd.framework_path(dir);
-            } else {
-                cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
-            }
-            ControlFlow::<()>::Continue(())
-        },
-    );
+    let fallback = Some(NativeLibSearchFallback { self_contained_components, apple_sdk_root });
+    walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| {
+        if is_framework {
+            cmd.framework_path(dir);
+        } else {
+            cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
+        }
+        ControlFlow::<()>::Continue(())
+    });
 }
 
 /// Add options making relocation sections in the produced ELF files read-only
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 87992ce2e11..9cc737d194c 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -475,7 +475,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
 ) -> OngoingCodegen<B> {
     let (coordinator_send, coordinator_receive) = channel();
 
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+    let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
 
     let crate_info = CrateInfo::new(tcx, target_cpu);
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 63f2f8fa3d1..e9c886d28ed 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -876,7 +876,7 @@ impl CrateInfo {
         let linked_symbols =
             crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
-        let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+        let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
         let subsystem =
             ast::attr::first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
         let windows_subsystem = subsystem.map(|subsystem| {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 27b8be1022e..998a4ff727e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -60,7 +60,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         );
     }
 
-    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(did));
+    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(did));
     let mut codegen_fn_attrs = CodegenFnAttrs::new();
     if tcx.should_inherit_track_caller(did) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
@@ -75,7 +75,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
 
     // When `no_builtins` is applied at the crate level, we should add the
     // `no-builtins` attribute to each function to ensure it takes effect in LTO.
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+    let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
     if no_builtins {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 4e758bfdec3..44b8cc459cf 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -2,6 +2,7 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -14,7 +15,6 @@
 #![feature(rustdoc_internals)]
 #![feature(trait_alias)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 23baab3124e..99f35b79208 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -205,7 +205,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer
             | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
 
             PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
+                NonMutatingUseContext::Copy
+                | NonMutatingUseContext::Move
+                // Inspect covers things like `PtrMetadata` and `Discriminant`
+                // which we can treat similar to `Copy` use for the purpose of
+                // whether we can use SSA variables for things.
+                | NonMutatingUseContext::Inspect,
             ) => match &mut self.locals[local] {
                 LocalKind::ZST => {}
                 LocalKind::Memory => {}
@@ -229,8 +234,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer
                 | MutatingUseContext::Projection,
             )
             | PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::Inspect
-                | NonMutatingUseContext::SharedBorrow
+                NonMutatingUseContext::SharedBorrow
                 | NonMutatingUseContext::FakeBorrow
                 | NonMutatingUseContext::RawBorrow
                 | NonMutatingUseContext::Projection,
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index b34e966ba6c..63025a4574f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let callee_ty = instance.ty(bx.tcx(), bx.typing_env());
 
         let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
-            bug!("expected fn item type, found {}", callee_ty);
+            span_bug!(span, "expected fn item type, found {}", callee_ty);
         };
 
         let sig = callee_ty.fn_sig(bx.tcx());
@@ -325,14 +325,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
 
-            sym::discriminant_value => {
-                if ret_ty.is_integral() {
-                    args[0].deref(bx.cx()).codegen_get_discr(bx, ret_ty)
-                } else {
-                    span_bug!(span, "Invalid discriminant type for `{:?}`", arg_tys[0])
-                }
-            }
-
             // This requires that atomic intrinsics follow a specific naming pattern:
             // "atomic_<operation>[_<ordering>]"
             name if let Some(atomic) = name_str.strip_prefix("atomic_") => {
@@ -441,6 +433,40 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
 
                     // These are all AtomicRMW ops
+                    "max" | "min" => {
+                        let atom_op = if instruction == "max" {
+                            AtomicRmwBinOp::AtomicMax
+                        } else {
+                            AtomicRmwBinOp::AtomicMin
+                        };
+
+                        let ty = fn_args.type_at(0);
+                        if matches!(ty.kind(), ty::Int(_)) {
+                            let ptr = args[0].immediate();
+                            let val = args[1].immediate();
+                            bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering))
+                        } else {
+                            invalid_monomorphization(ty);
+                            return Ok(());
+                        }
+                    }
+                    "umax" | "umin" => {
+                        let atom_op = if instruction == "umax" {
+                            AtomicRmwBinOp::AtomicUMax
+                        } else {
+                            AtomicRmwBinOp::AtomicUMin
+                        };
+
+                        let ty = fn_args.type_at(0);
+                        if matches!(ty.kind(), ty::Uint(_)) {
+                            let ptr = args[0].immediate();
+                            let val = args[1].immediate();
+                            bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering))
+                        } else {
+                            invalid_monomorphization(ty);
+                            return Ok(());
+                        }
+                    }
                     op => {
                         let atom_op = match op {
                             "xchg" => AtomicRmwBinOp::AtomicXchg,
@@ -450,10 +476,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             "nand" => AtomicRmwBinOp::AtomicNand,
                             "or" => AtomicRmwBinOp::AtomicOr,
                             "xor" => AtomicRmwBinOp::AtomicXor,
-                            "max" => AtomicRmwBinOp::AtomicMax,
-                            "min" => AtomicRmwBinOp::AtomicMin,
-                            "umax" => AtomicRmwBinOp::AtomicUMax,
-                            "umin" => AtomicRmwBinOp::AtomicUMin,
                             _ => bx.sess().dcx().emit_fatal(errors::UnknownAtomicOperation),
                         };
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index 96d1ab018f6..bc9cde1b2a1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -125,7 +125,8 @@ fn prefix_and_suffix<'tcx>(
     // the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
     // if no alignment is specified, an alignment of 4 bytes is used.
     let min_function_alignment = tcx.sess.opts.unstable_opts.min_function_alignment;
-    let align = Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4);
+    let align_bytes =
+        Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4);
 
     // In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`.
     let (arch_prefix, arch_suffix) = if is_arm {
@@ -157,12 +158,16 @@ fn prefix_and_suffix<'tcx>(
             }
             Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => {
                 match asm_binary_format {
-                    BinaryFormat::Elf
-                    | BinaryFormat::Coff
-                    | BinaryFormat::Wasm
-                    | BinaryFormat::Xcoff => {
+                    BinaryFormat::Elf | BinaryFormat::Coff | BinaryFormat::Wasm => {
                         writeln!(w, ".weak {asm_name}")?;
                     }
+                    BinaryFormat::Xcoff => {
+                        // FIXME: there is currently no way of defining a weak symbol in inline assembly
+                        // for AIX. See https://github.com/llvm/llvm-project/issues/130269
+                        emit_fatal(
+                            "cannot create weak symbols from inline assembly for this target",
+                        )
+                    }
                     BinaryFormat::MachO => {
                         writeln!(w, ".globl {asm_name}")?;
                         writeln!(w, ".weak_definition {asm_name}")?;
@@ -189,7 +194,7 @@ fn prefix_and_suffix<'tcx>(
     let mut begin = String::new();
     let mut end = String::new();
     match asm_binary_format {
-        BinaryFormat::Elf | BinaryFormat::Xcoff => {
+        BinaryFormat::Elf => {
             let section = link_section.unwrap_or(format!(".text.{asm_name}"));
 
             let progbits = match is_arm {
@@ -203,7 +208,7 @@ fn prefix_and_suffix<'tcx>(
             };
 
             writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap();
-            writeln!(begin, ".balign {align}").unwrap();
+            writeln!(begin, ".balign {align_bytes}").unwrap();
             write_linkage(&mut begin).unwrap();
             if let Visibility::Hidden = item_data.visibility {
                 writeln!(begin, ".hidden {asm_name}").unwrap();
@@ -224,7 +229,7 @@ fn prefix_and_suffix<'tcx>(
         BinaryFormat::MachO => {
             let section = link_section.unwrap_or("__TEXT,__text".to_string());
             writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap();
-            writeln!(begin, ".balign {align}").unwrap();
+            writeln!(begin, ".balign {align_bytes}").unwrap();
             write_linkage(&mut begin).unwrap();
             if let Visibility::Hidden = item_data.visibility {
                 writeln!(begin, ".private_extern {asm_name}").unwrap();
@@ -240,12 +245,12 @@ fn prefix_and_suffix<'tcx>(
         BinaryFormat::Coff => {
             let section = link_section.unwrap_or(format!(".text.{asm_name}"));
             writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
-            writeln!(begin, ".balign {align}").unwrap();
+            writeln!(begin, ".balign {align_bytes}").unwrap();
             write_linkage(&mut begin).unwrap();
             writeln!(begin, ".def {asm_name}").unwrap();
             writeln!(begin, ".scl 2").unwrap();
             writeln!(begin, ".type 32").unwrap();
-            writeln!(begin, ".endef {asm_name}").unwrap();
+            writeln!(begin, ".endef").unwrap();
             writeln!(begin, "{asm_name}:").unwrap();
 
             writeln!(end).unwrap();
@@ -279,6 +284,33 @@ fn prefix_and_suffix<'tcx>(
             // .size is ignored for function symbols, so we can skip it
             writeln!(end, "end_function").unwrap();
         }
+        BinaryFormat::Xcoff => {
+            // the LLVM XCOFFAsmParser is extremely incomplete and does not implement many of the
+            // documented directives.
+            //
+            // - https://github.com/llvm/llvm-project/blob/1b25c0c4da968fe78921ce77736e5baef4db75e3/llvm/lib/MC/MCParser/XCOFFAsmParser.cpp
+            // - https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf
+            //
+            // Consequently, we try our best here but cannot do as good a job as for other binary
+            // formats.
+
+            // FIXME: start a section. `.csect` is not currently implemented in LLVM
+
+            // fun fact: according to the assembler documentation, .align takes an exponent,
+            // but LLVM only accepts powers of 2 (but does emit the exponent)
+            // so when we hand `.align 32` to LLVM, the assembly output will contain `.align 5`
+            writeln!(begin, ".align {}", align_bytes).unwrap();
+
+            write_linkage(&mut begin).unwrap();
+            if let Visibility::Hidden = item_data.visibility {
+                // FIXME apparently `.globl {asm_name}, hidden` is valid
+                // but due to limitations with `.weak` (see above) we can't really use that in general yet
+            }
+            writeln!(begin, "{asm_name}:").unwrap();
+
+            writeln!(end).unwrap();
+            // FIXME: end the section?
+        }
     }
 
     (begin, end)
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index acae09b2c25..7e355b6406a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -3,16 +3,17 @@ use std::fmt;
 use arrayvec::ArrayVec;
 use either::Either;
 use rustc_abi as abi;
-use rustc_abi::{Align, BackendRepr, Size};
+use rustc_abi::{Align, BackendRepr, FIRST_VARIANT, Primitive, Size, TagEncoding, Variants};
 use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range};
 use rustc_middle::mir::{self, ConstValue};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::{bug, span_bug};
-use tracing::debug;
+use tracing::{debug, instrument};
 
 use super::place::{PlaceRef, PlaceValue};
 use super::{FunctionCx, LocalRef};
+use crate::common::IntPredicate;
 use crate::traits::*;
 use crate::{MemFlags, size_of_val};
 
@@ -415,6 +416,149 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
         OperandRef { val, layout: field }
     }
+
+    /// Obtain the actual discriminant of a value.
+    #[instrument(level = "trace", skip(fx, bx))]
+    pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        self,
+        fx: &mut FunctionCx<'a, 'tcx, Bx>,
+        bx: &mut Bx,
+        cast_to: Ty<'tcx>,
+    ) -> V {
+        let dl = &bx.tcx().data_layout;
+        let cast_to_layout = bx.cx().layout_of(cast_to);
+        let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
+
+        // We check uninhabitedness separately because a type like
+        // `enum Foo { Bar(i32, !) }` is still reported as `Variants::Single`,
+        // *not* as `Variants::Empty`.
+        if self.layout.is_uninhabited() {
+            return bx.cx().const_poison(cast_to);
+        }
+
+        let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
+            Variants::Empty => unreachable!("we already handled uninhabited types"),
+            Variants::Single { index } => {
+                let discr_val =
+                    if let Some(discr) = self.layout.ty.discriminant_for_variant(bx.tcx(), index) {
+                        discr.val
+                    } else {
+                        // This arm is for types which are neither enums nor coroutines,
+                        // and thus for which the only possible "variant" should be the first one.
+                        assert_eq!(index, FIRST_VARIANT);
+                        // There's thus no actual discriminant to return, so we return
+                        // what it would have been if this was a single-variant enum.
+                        0
+                    };
+                return bx.cx().const_uint_big(cast_to, discr_val);
+            }
+            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
+                (tag, tag_encoding, tag_field)
+            }
+        };
+
+        // Read the tag/niche-encoded discriminant from memory.
+        let tag_op = match self.val {
+            OperandValue::ZeroSized => bug!(),
+            OperandValue::Immediate(_) | OperandValue::Pair(_, _) => {
+                self.extract_field(fx, bx, tag_field)
+            }
+            OperandValue::Ref(place) => {
+                let tag = place.with_type(self.layout).project_field(bx, tag_field);
+                bx.load_operand(tag)
+            }
+        };
+        let tag_imm = tag_op.immediate();
+
+        // Decode the discriminant (specifically if it's niche-encoded).
+        match *tag_encoding {
+            TagEncoding::Direct => {
+                let signed = match tag_scalar.primitive() {
+                    // We use `i1` for bytes that are always `0` or `1`,
+                    // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
+                    // let LLVM interpret the `i1` as signed, because
+                    // then `i1 1` (i.e., `E::B`) is effectively `i8 -1`.
+                    Primitive::Int(_, signed) => !tag_scalar.is_bool() && signed,
+                    _ => false,
+                };
+                bx.intcast(tag_imm, cast_to, signed)
+            }
+            TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
+                // Cast to an integer so we don't have to treat a pointer as a
+                // special case.
+                let (tag, tag_llty) = match tag_scalar.primitive() {
+                    // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+                    Primitive::Pointer(_) => {
+                        let t = bx.type_from_integer(dl.ptr_sized_integer());
+                        let tag = bx.ptrtoint(tag_imm, t);
+                        (tag, t)
+                    }
+                    _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)),
+                };
+
+                let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+
+                // We have a subrange `niche_start..=niche_end` inside `range`.
+                // If the value of the tag is inside this subrange, it's a
+                // "niche value", an increment of the discriminant. Otherwise it
+                // indicates the untagged variant.
+                // A general algorithm to extract the discriminant from the tag
+                // is:
+                // relative_tag = tag - niche_start
+                // is_niche = relative_tag <= (ule) relative_max
+                // discr = if is_niche {
+                //     cast(relative_tag) + niche_variants.start()
+                // } else {
+                //     untagged_variant
+                // }
+                // However, we will likely be able to emit simpler code.
+                let (is_niche, tagged_discr, delta) = if relative_max == 0 {
+                    // Best case scenario: only one tagged variant. This will
+                    // likely become just a comparison and a jump.
+                    // The algorithm is:
+                    // is_niche = tag == niche_start
+                    // discr = if is_niche {
+                    //     niche_start
+                    // } else {
+                    //     untagged_variant
+                    // }
+                    let niche_start = bx.cx().const_uint_big(tag_llty, niche_start);
+                    let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start);
+                    let tagged_discr =
+                        bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64);
+                    (is_niche, tagged_discr, 0)
+                } else {
+                    // The special cases don't apply, so we'll have to go with
+                    // the general algorithm.
+                    let relative_discr = bx.sub(tag, bx.cx().const_uint_big(tag_llty, niche_start));
+                    let cast_tag = bx.intcast(relative_discr, cast_to, false);
+                    let is_niche = bx.icmp(
+                        IntPredicate::IntULE,
+                        relative_discr,
+                        bx.cx().const_uint(tag_llty, relative_max as u64),
+                    );
+                    (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
+                };
+
+                let tagged_discr = if delta == 0 {
+                    tagged_discr
+                } else {
+                    bx.add(tagged_discr, bx.cx().const_uint_big(cast_to, delta))
+                };
+
+                let discr = bx.select(
+                    is_niche,
+                    tagged_discr,
+                    bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64),
+                );
+
+                // In principle we could insert assumes on the possible range of `discr`, but
+                // currently in LLVM this seems to be a pessimization.
+
+                discr
+            }
+        }
+    }
 }
 
 impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 6988724b421..31db7fa9a18 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -1,4 +1,3 @@
-use rustc_abi::Primitive::{Int, Pointer};
 use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
 use rustc_middle::mir::PlaceTy;
 use rustc_middle::mir::interpret::Scalar;
@@ -233,129 +232,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         val.with_type(field)
     }
 
-    /// Obtain the actual discriminant of a value.
-    #[instrument(level = "trace", skip(bx))]
-    pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        self,
-        bx: &mut Bx,
-        cast_to: Ty<'tcx>,
-    ) -> V {
-        let dl = &bx.tcx().data_layout;
-        let cast_to_layout = bx.cx().layout_of(cast_to);
-        let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
-        if self.layout.is_uninhabited() {
-            return bx.cx().const_poison(cast_to);
-        }
-        let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
-            Variants::Empty => unreachable!("we already handled uninhabited types"),
-            Variants::Single { index } => {
-                let discr_val = self
-                    .layout
-                    .ty
-                    .discriminant_for_variant(bx.cx().tcx(), index)
-                    .map_or(index.as_u32() as u128, |discr| discr.val);
-                return bx.cx().const_uint_big(cast_to, discr_val);
-            }
-            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
-                (tag, tag_encoding, tag_field)
-            }
-        };
-
-        // Read the tag/niche-encoded discriminant from memory.
-        let tag = self.project_field(bx, tag_field);
-        let tag_op = bx.load_operand(tag);
-        let tag_imm = tag_op.immediate();
-
-        // Decode the discriminant (specifically if it's niche-encoded).
-        match *tag_encoding {
-            TagEncoding::Direct => {
-                let signed = match tag_scalar.primitive() {
-                    // We use `i1` for bytes that are always `0` or `1`,
-                    // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
-                    // let LLVM interpret the `i1` as signed, because
-                    // then `i1 1` (i.e., `E::B`) is effectively `i8 -1`.
-                    Int(_, signed) => !tag_scalar.is_bool() && signed,
-                    _ => false,
-                };
-                bx.intcast(tag_imm, cast_to, signed)
-            }
-            TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
-                // Cast to an integer so we don't have to treat a pointer as a
-                // special case.
-                let (tag, tag_llty) = match tag_scalar.primitive() {
-                    // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
-                    Pointer(_) => {
-                        let t = bx.type_from_integer(dl.ptr_sized_integer());
-                        let tag = bx.ptrtoint(tag_imm, t);
-                        (tag, t)
-                    }
-                    _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)),
-                };
-
-                let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
-
-                // We have a subrange `niche_start..=niche_end` inside `range`.
-                // If the value of the tag is inside this subrange, it's a
-                // "niche value", an increment of the discriminant. Otherwise it
-                // indicates the untagged variant.
-                // A general algorithm to extract the discriminant from the tag
-                // is:
-                // relative_tag = tag - niche_start
-                // is_niche = relative_tag <= (ule) relative_max
-                // discr = if is_niche {
-                //     cast(relative_tag) + niche_variants.start()
-                // } else {
-                //     untagged_variant
-                // }
-                // However, we will likely be able to emit simpler code.
-                let (is_niche, tagged_discr, delta) = if relative_max == 0 {
-                    // Best case scenario: only one tagged variant. This will
-                    // likely become just a comparison and a jump.
-                    // The algorithm is:
-                    // is_niche = tag == niche_start
-                    // discr = if is_niche {
-                    //     niche_start
-                    // } else {
-                    //     untagged_variant
-                    // }
-                    let niche_start = bx.cx().const_uint_big(tag_llty, niche_start);
-                    let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start);
-                    let tagged_discr =
-                        bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64);
-                    (is_niche, tagged_discr, 0)
-                } else {
-                    // The special cases don't apply, so we'll have to go with
-                    // the general algorithm.
-                    let relative_discr = bx.sub(tag, bx.cx().const_uint_big(tag_llty, niche_start));
-                    let cast_tag = bx.intcast(relative_discr, cast_to, false);
-                    let is_niche = bx.icmp(
-                        IntPredicate::IntULE,
-                        relative_discr,
-                        bx.cx().const_uint(tag_llty, relative_max as u64),
-                    );
-                    (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
-                };
-
-                let tagged_discr = if delta == 0 {
-                    tagged_discr
-                } else {
-                    bx.add(tagged_discr, bx.cx().const_uint_big(cast_to, delta))
-                };
-
-                let discr = bx.select(
-                    is_niche,
-                    tagged_discr,
-                    bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64),
-                );
-
-                // In principle we could insert assumes on the possible range of `discr`, but
-                // currently in LLVM this seems to be a pessimization.
-
-                discr
-            }
-        }
-    }
-
     /// Sets the discriminant for a new value of the given case of the given
     /// representation.
     pub fn codegen_set_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 95b108b1d33..96be44ee09f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -706,7 +706,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::Rvalue::Discriminant(ref place) => {
                 let discr_ty = rvalue.ty(self.mir, bx.tcx());
                 let discr_ty = self.monomorphize(discr_ty);
-                let discr = self.codegen_place(bx, place.as_ref()).codegen_get_discr(bx, discr_ty);
+                let operand = self.codegen_consume(bx, place.as_ref());
+                let discr = operand.codegen_get_discr(self, bx, discr_ty);
                 OperandRef {
                     val: OperandValue::Immediate(discr),
                     layout: self.cx.layout_of(discr_ty),
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index 607cb2e497d..06ee7075170 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -81,7 +81,7 @@ pub fn rustc_allow_const_fn_unstable(
     def_id: LocalDefId,
     feature_gate: Symbol,
 ) -> bool {
-    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
+    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
 
     find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 1a799f5dea5..a21bf018d01 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -8,7 +8,6 @@ use std::hash::Hash;
 
 use rustc_abi::{Align, Size};
 use rustc_apfloat::{Float, FloatConvert};
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::TyAndLayout;
@@ -21,7 +20,6 @@ use super::{
     AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation,
     CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind,
     Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, interp_ok, throw_unsup,
-    throw_unsup_format,
 };
 
 /// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -361,6 +359,19 @@ pub trait Machine<'tcx>: Sized {
         size: i64,
     ) -> Option<(AllocId, Size, Self::ProvenanceExtra)>;
 
+    /// Return a "root" pointer for the given allocation: the one that is used for direct
+    /// accesses to this static/const/fn allocation, or the one returned from the heap allocator.
+    ///
+    /// Not called on `extern` or thread-local statics (those use the methods above).
+    ///
+    /// `kind` is the kind of the allocation the pointer points to; it can be `None` when
+    /// it's a global and `GLOBAL_KIND` is `None`.
+    fn adjust_alloc_root_pointer(
+        ecx: &InterpCx<'tcx, Self>,
+        ptr: Pointer,
+        kind: Option<MemoryKind<Self::MemoryKind>>,
+    ) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
+
     /// Called to adjust global allocations to the Provenance and AllocExtra of this machine.
     ///
     /// If `alloc` contains pointers, then they are all pointing to globals.
@@ -375,11 +386,12 @@ pub trait Machine<'tcx>: Sized {
         alloc: &'b Allocation,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
 
-    /// Initialize the extra state of an allocation.
+    /// Initialize the extra state of an allocation local to this machine.
     ///
-    /// This is guaranteed to be called exactly once on all allocations that are accessed by the
-    /// program.
-    fn init_alloc_extra(
+    /// This is guaranteed to be called exactly once on all allocations local to this machine.
+    /// It will not be called automatically for global allocations; `adjust_global_allocation`
+    /// has to do that itself if that is desired.
+    fn init_local_allocation(
         ecx: &InterpCx<'tcx, Self>,
         id: AllocId,
         kind: MemoryKind<Self::MemoryKind>,
@@ -387,34 +399,6 @@ pub trait Machine<'tcx>: Sized {
         align: Align,
     ) -> InterpResult<'tcx, Self::AllocExtra>;
 
-    /// Return a "root" pointer for the given allocation: the one that is used for direct
-    /// accesses to this static/const/fn allocation, or the one returned from the heap allocator.
-    ///
-    /// Not called on `extern` or thread-local statics (those use the methods above).
-    ///
-    /// `kind` is the kind of the allocation the pointer points to; it can be `None` when
-    /// it's a global and `GLOBAL_KIND` is `None`.
-    fn adjust_alloc_root_pointer(
-        ecx: &InterpCx<'tcx, Self>,
-        ptr: Pointer,
-        kind: Option<MemoryKind<Self::MemoryKind>>,
-    ) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
-
-    /// Evaluate the inline assembly.
-    ///
-    /// This should take care of jumping to the next block (one of `targets`) when asm goto
-    /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
-    /// naked_asm! or `InlineAsmOptions::NORETURN` being set.
-    fn eval_inline_asm(
-        _ecx: &mut InterpCx<'tcx, Self>,
-        _template: &'tcx [InlineAsmTemplatePiece],
-        _operands: &[mir::InlineAsmOperand<'tcx>],
-        _options: InlineAsmOptions,
-        _targets: &[mir::BasicBlock],
-    ) -> InterpResult<'tcx> {
-        throw_unsup_format!("inline assembly is not supported")
-    }
-
     /// Hook for performing extra checks on a memory read access.
     ///
     /// This will *not* be called during validation!
@@ -699,7 +683,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
         interp_ok(Cow::Borrowed(alloc))
     }
 
-    fn init_alloc_extra(
+    fn init_local_allocation(
         _ecx: &InterpCx<$tcx, Self>,
         _id: AllocId,
         _kind: MemoryKind<Self::MemoryKind>,
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index e5af0673629..75726269a86 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -263,9 +263,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             M::GLOBAL_KIND.map(MemoryKind::Machine),
             "dynamically allocating global memory"
         );
-        // We have set things up so we don't need to call `adjust_from_tcx` here,
-        // so we avoid copying the entire allocation contents.
-        let extra = M::init_alloc_extra(self, id, kind, alloc.size(), alloc.align)?;
+        // This cannot be merged with the `adjust_global_allocation` code path
+        // since here we have an allocation that already uses `M::Bytes`.
+        let extra = M::init_local_allocation(self, id, kind, alloc.size(), alloc.align)?;
         let alloc = alloc.with_extra(extra);
         self.memory.alloc_map.insert(id, (kind, alloc));
         M::adjust_alloc_root_pointer(self, Pointer::from(id), Some(kind))
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 6a17da61c8b..ddf2d65914f 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -14,7 +14,7 @@ use tracing::{info, instrument, trace};
 
 use super::{
     FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy,
-    Projectable, Scalar, interp_ok, throw_ub,
+    Projectable, Scalar, interp_ok, throw_ub, throw_unsup_format,
 };
 use crate::util;
 
@@ -590,8 +590,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 terminator.kind
             ),
 
-            InlineAsm { template, ref operands, options, ref targets, .. } => {
-                M::eval_inline_asm(self, template, operands, options, targets)?;
+            InlineAsm { .. } => {
+                throw_unsup_format!("inline assembly is not supported");
             }
         }
 
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index ed5489652fb..e03849c32f9 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -1,6 +1,7 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -16,7 +17,6 @@
 #![feature(unqualified_local_imports)]
 #![feature(yeet_expr)]
 #![warn(unqualified_local_imports)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod check_consts;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index bdf5494f210..b9a5fc3a1fe 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -29,6 +29,11 @@ thin-vec = "0.2.12"
 tracing = "0.1"
 # tidy-alphabetical-end
 
+[dependencies.hashbrown]
+version = "0.15.2"
+default-features = false
+features = ["nightly"] # for may_dangle
+
 [dependencies.parking_lot]
 version = "0.12"
 
diff --git a/compiler/rustc_data_structures/src/graph/tests.rs b/compiler/rustc_data_structures/src/graph/tests.rs
index b69b9dbc4a8..e48b9686c26 100644
--- a/compiler/rustc_data_structures/src/graph/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/tests.rs
@@ -3,7 +3,7 @@ use std::cmp::max;
 use super::*;
 use crate::fx::FxHashMap;
 
-pub struct TestGraph {
+pub(super) struct TestGraph {
     num_nodes: usize,
     start_node: usize,
     successors: FxHashMap<usize, Vec<usize>>,
@@ -11,7 +11,7 @@ pub struct TestGraph {
 }
 
 impl TestGraph {
-    pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
+    pub(super) fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
         let mut graph = TestGraph {
             num_nodes: start_node + 1,
             start_node,
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index a3b62b46919..865424fd6bb 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -24,7 +24,6 @@
 #![feature(dropck_eyepatch)]
 #![feature(extend_one)]
 #![feature(file_buffered)]
-#![feature(hash_raw_entry)]
 #![feature(macro_metavar_expr)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 4cacc269709..64c64bfa3c2 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -76,6 +76,7 @@ impl_dyn_send!(
     [crate::sync::RwLock<T> where T: DynSend]
     [crate::tagged_ptr::TaggedRef<'a, P, T> where 'a, P: Sync, T: Send + crate::tagged_ptr::Tag]
     [rustc_arena::TypedArena<T> where T: DynSend]
+    [hashbrown::HashTable<T> where T: DynSend]
     [indexmap::IndexSet<V, S> where V: DynSend, S: DynSend]
     [indexmap::IndexMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
     [thin_vec::ThinVec<T> where T: DynSend]
@@ -153,6 +154,7 @@ impl_dyn_sync!(
     [crate::tagged_ptr::TaggedRef<'a, P, T> where 'a, P: Sync, T: Sync + crate::tagged_ptr::Tag]
     [parking_lot::lock_api::Mutex<R, T> where R: DynSync, T: ?Sized + DynSend]
     [parking_lot::lock_api::RwLock<R, T> where R: DynSync, T: ?Sized + DynSend + DynSync]
+    [hashbrown::HashTable<T> where T: DynSync]
     [indexmap::IndexSet<V, S> where V: DynSync, S: DynSync]
     [indexmap::IndexMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
     [smallvec::SmallVec<A> where A: smallvec::Array + DynSync]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index ea3ac467340..f63b201742d 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -313,7 +313,7 @@ pub struct Error<O, E> {
 
 mod helper {
     use super::*;
-    pub type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
+    pub(super) type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
     impl<O: ForestObligation> ObligationForest<O> {
         #[cfg_attr(not(bootstrap), define_opaque(ObligationTreeIdGenerator))]
         pub fn new() -> ObligationForest<O> {
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 3016348f224..49cafcb17a0 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -1,11 +1,11 @@
 use std::borrow::Borrow;
-use std::collections::hash_map::RawEntryMut;
 use std::hash::{Hash, Hasher};
-use std::iter;
+use std::{iter, mem};
 
 use either::Either;
+use hashbrown::hash_table::{Entry, HashTable};
 
-use crate::fx::{FxHashMap, FxHasher};
+use crate::fx::FxHasher;
 use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe};
 
 // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
@@ -140,17 +140,67 @@ pub fn shards() -> usize {
     1
 }
 
-pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>;
+pub type ShardedHashMap<K, V> = Sharded<HashTable<(K, V)>>;
 
 impl<K: Eq, V> ShardedHashMap<K, V> {
     pub fn with_capacity(cap: usize) -> Self {
-        Self::new(|| FxHashMap::with_capacity_and_hasher(cap, rustc_hash::FxBuildHasher::default()))
+        Self::new(|| HashTable::with_capacity(cap))
     }
     pub fn len(&self) -> usize {
         self.lock_shards().map(|shard| shard.len()).sum()
     }
 }
 
+impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
+    #[inline]
+    pub fn get<Q>(&self, key: &Q) -> Option<V>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+        V: Clone,
+    {
+        let hash = make_hash(key);
+        let shard = self.lock_shard_by_hash(hash);
+        let (_, value) = shard.find(hash, |(k, _)| k.borrow() == key)?;
+        Some(value.clone())
+    }
+
+    #[inline]
+    pub fn get_or_insert_with(&self, key: K, default: impl FnOnce() -> V) -> V
+    where
+        V: Copy,
+    {
+        let hash = make_hash(&key);
+        let mut shard = self.lock_shard_by_hash(hash);
+
+        match table_entry(&mut shard, hash, &key) {
+            Entry::Occupied(e) => e.get().1,
+            Entry::Vacant(e) => {
+                let value = default();
+                e.insert((key, value));
+                value
+            }
+        }
+    }
+
+    #[inline]
+    pub fn insert(&self, key: K, value: V) -> Option<V> {
+        let hash = make_hash(&key);
+        let mut shard = self.lock_shard_by_hash(hash);
+
+        match table_entry(&mut shard, hash, &key) {
+            Entry::Occupied(e) => {
+                let previous = mem::replace(&mut e.into_mut().1, value);
+                Some(previous)
+            }
+            Entry::Vacant(e) => {
+                e.insert((key, value));
+                None
+            }
+        }
+    }
+}
+
 impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     #[inline]
     pub fn intern_ref<Q: ?Sized>(&self, value: &Q, make: impl FnOnce() -> K) -> K
@@ -160,13 +210,12 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     {
         let hash = make_hash(value);
         let mut shard = self.lock_shard_by_hash(hash);
-        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, value);
 
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
+        match table_entry(&mut shard, hash, value) {
+            Entry::Occupied(e) => e.get().0,
+            Entry::Vacant(e) => {
                 let v = make();
-                e.insert_hashed_nocheck(hash, v, ());
+                e.insert((v, ()));
                 v
             }
         }
@@ -180,13 +229,12 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     {
         let hash = make_hash(&value);
         let mut shard = self.lock_shard_by_hash(hash);
-        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value);
 
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
+        match table_entry(&mut shard, hash, &value) {
+            Entry::Occupied(e) => e.get().0,
+            Entry::Vacant(e) => {
                 let v = make(value);
-                e.insert_hashed_nocheck(hash, v, ());
+                e.insert((v, ()));
                 v
             }
         }
@@ -203,17 +251,30 @@ impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
         let hash = make_hash(&value);
         let shard = self.lock_shard_by_hash(hash);
         let value = value.into_pointer();
-        shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
+        shard.find(hash, |(k, ())| k.into_pointer() == value).is_some()
     }
 }
 
 #[inline]
-pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
+fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
     let mut state = FxHasher::default();
     val.hash(&mut state);
     state.finish()
 }
 
+#[inline]
+fn table_entry<'a, K, V, Q>(
+    table: &'a mut HashTable<(K, V)>,
+    hash: u64,
+    key: &Q,
+) -> Entry<'a, (K, V)>
+where
+    K: Hash + Borrow<Q>,
+    Q: ?Sized + Eq,
+{
+    table.entry(hash, move |(k, _)| k.borrow() == key, |(k, _)| make_hash(k))
+}
+
 /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is
 /// ever used in combination with `get_shard_by_hash` on a single `Sharded`
 /// instance, then `hash` must be computed with `FxHasher`. Otherwise,
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index a1cc75c4985..616a18a72ab 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -88,7 +88,7 @@ mod mode {
 
     // Whether thread safety might be enabled.
     #[inline]
-    pub fn might_be_dyn_thread_safe() -> bool {
+    pub(super) fn might_be_dyn_thread_safe() -> bool {
         DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) != DYN_NOT_THREAD_SAFE
     }
 
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index 1ba631b8623..8ef8a3f3585 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -46,7 +46,7 @@ pub fn parallel_guard<R>(f: impl FnOnce(&ParallelGuard) -> R) -> R {
     ret
 }
 
-pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
+fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
 where
     A: FnOnce() -> RA,
     B: FnOnce() -> RB,
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
index 9c1e4cefa69..85b21a7c8ec 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
@@ -7,7 +7,7 @@ use crate::stable_hasher::{HashStable, StableHasher};
 
 /// A tag type used in [`TaggedRef`] tests.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Tag2 {
+enum Tag2 {
     B00 = 0b00,
     B01 = 0b01,
     B10 = 0b10,
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index a03834c519d..381309f83b2 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -3,6 +3,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index a2ddff7183e..ed5662da16d 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -7,6 +7,7 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(decl_macro)]
@@ -16,7 +17,6 @@
 #![feature(result_flattening)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::cmp::max;
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 828a14e707c..16d70af7e05 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -268,8 +268,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
             let tcx = ex.tcx();
             let f = |annotation: &dyn pprust_hir::PpAnn| {
                 let sm = sess.source_map();
-                let hir_map = tcx.hir();
-                let attrs = |id| hir_map.attrs(id);
+                let attrs = |id| tcx.hir_attrs(id);
                 pprust_hir::print_crate(
                     sm,
                     tcx.hir_root_module(),
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index d53d5678832..dfeef5a957d 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -6,7 +6,6 @@
 #![deny(rustdoc::invalid_codeblock_attributes)]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 // This higher-order macro defines the error codes that are in use. It is used
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 6d02d6370fc..39e78ae8841 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 #![feature(type_alias_impl_trait)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::borrow::Cow;
@@ -107,8 +106,8 @@ impl From<Vec<FluentError>> for TranslationBundleError {
 /// (overriding any conflicting messages).
 #[instrument(level = "trace")]
 pub fn fluent_bundle(
-    mut user_provided_sysroot: Option<PathBuf>,
-    mut sysroot_candidates: Vec<PathBuf>,
+    sysroot: PathBuf,
+    sysroot_candidates: Vec<PathBuf>,
     requested_locale: Option<LanguageIdentifier>,
     additional_ftl_path: Option<&Path>,
     with_directionality_markers: bool,
@@ -142,7 +141,7 @@ pub fn fluent_bundle(
     // If the user requests the default locale then don't try to load anything.
     if let Some(requested_locale) = requested_locale {
         let mut found_resources = false;
-        for sysroot in user_provided_sysroot.iter_mut().chain(sysroot_candidates.iter_mut()) {
+        for mut sysroot in Some(sysroot).into_iter().chain(sysroot_candidates.into_iter()) {
             sysroot.push("share");
             sysroot.push("locale");
             sysroot.push(requested_locale.to_string());
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 86959b28e53..80e43ede445 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -25,7 +25,6 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate self as rustc_errors;
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 86b12f6be4e..895efe05e11 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
 
 use rustc_ast::attr::{AttributeExt, MarkedAttrs};
 use rustc_ast::ptr::P;
-use rustc_ast::token::Nonterminal;
+use rustc_ast::token::MetaVarKind;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
@@ -19,7 +19,7 @@ use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
 use rustc_parse::MACRO_ARGUMENTS;
-use rustc_parse::parser::Parser;
+use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::config::CollapseMacroDebuginfo;
 use rustc_session::parse::ParseSess;
 use rustc_session::{Limit, Session};
@@ -1405,13 +1405,13 @@ pub fn parse_macro_name_and_helper_attrs(
 /// If this item looks like a specific enums from `rental`, emit a fatal error.
 /// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
-fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
+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
         && let [variant] = &*enum_def.variants
         && variant.ident.name == sym::Input
-        && let FileName::Real(real) = sess.source_map().span_to_filename(item.ident.span)
+        && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span)
         && let Some(c) = real
             .local_path()
             .unwrap_or(Path::new(""))
@@ -1429,7 +1429,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
         };
 
         if crate_matches {
-            sess.dcx().emit_fatal(errors::ProcMacroBackCompat {
+            psess.dcx().emit_fatal(errors::ProcMacroBackCompat {
                 crate_name: "rental".to_string(),
                 fixed_version: "0.5.6".to_string(),
             });
@@ -1437,7 +1437,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
     }
 }
 
-pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) {
+pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: &ParseSess) {
     let item = match ann {
         Annotatable::Item(item) => item,
         Annotatable::Stmt(stmt) => match &stmt.kind {
@@ -1446,17 +1446,36 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &S
         },
         _ => return,
     };
-    pretty_printing_compatibility_hack(item, sess)
+    pretty_printing_compatibility_hack(item, psess)
 }
 
-pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) {
-    let item = match nt {
-        Nonterminal::NtItem(item) => item,
-        Nonterminal::NtStmt(stmt) => match &stmt.kind {
-            ast::StmtKind::Item(item) => item,
-            _ => return,
-        },
+pub(crate) fn stream_pretty_printing_compatibility_hack(
+    kind: MetaVarKind,
+    stream: &TokenStream,
+    psess: &ParseSess,
+) {
+    let item = match kind {
+        MetaVarKind::Item => {
+            let mut parser = Parser::new(psess, stream.clone(), None);
+            // No need to collect tokens for this simple check.
+            parser
+                .parse_item(ForceCollect::No)
+                .expect("failed to reparse item")
+                .expect("an actual item")
+        }
+        MetaVarKind::Stmt => {
+            let mut parser = Parser::new(psess, stream.clone(), None);
+            // No need to collect tokens for this simple check.
+            let stmt = parser
+                .parse_stmt(ForceCollect::No)
+                .expect("failed to reparse")
+                .expect("an actual stmt");
+            match &stmt.kind {
+                ast::StmtKind::Item(item) => item.clone(),
+                _ => return,
+            }
+        }
         _ => return,
     };
-    pretty_printing_compatibility_hack(item, sess)
+    pretty_printing_compatibility_hack(&item, psess)
 }
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 777044e3f33..4222c9fe906 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -13,7 +13,6 @@
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate proc_macro as pm;
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 70107c80147..cffa4af6ac3 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -7,7 +7,7 @@ use rustc_ast::token::{
     TokenKind,
 };
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
-use rustc_ast::{ExprKind, TyKind};
+use rustc_ast::{ExprKind, StmtKind, TyKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
 use rustc_parse::lexer::nfc_normalize;
@@ -323,6 +323,18 @@ pub(super) fn transcribe<'a>(
                             let kind = token::NtLifetime(*ident, *is_raw);
                             TokenTree::token_alone(kind, sp)
                         }
+                        MatchedSingle(ParseNtResult::Item(item)) => {
+                            mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item))
+                        }
+                        MatchedSingle(ParseNtResult::Stmt(stmt)) => {
+                            let stream = if let StmtKind::Empty = stmt.kind {
+                                // FIXME: Properly collect tokens for empty statements.
+                                TokenStream::token_alone(token::Semi, stmt.span)
+                            } else {
+                                TokenStream::from_ast(stmt)
+                            };
+                            mk_delimited(stmt.span, MetaVarKind::Stmt, stream)
+                        }
                         MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => mk_delimited(
                             pat.span,
                             MetaVarKind::Pat(*pat_kind),
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index a6cdeaee176..d5af9849e75 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -122,7 +122,7 @@ impl MultiItemModifier for DeriveProcMacro {
         // We had a lint for a long time, but now we just emit a hard error.
         // Eventually we might remove the special case hard error check
         // altogether. See #73345.
-        crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
+        crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.psess);
         let input = item.to_tokens();
         let stream = {
             let _timer =
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 007241437ec..e0269eb6903 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -115,11 +115,43 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
 
         while let Some(tree) = iter.next() {
             let (Token { kind, span }, joint) = match tree.clone() {
-                tokenstream::TokenTree::Delimited(span, _, delim, tts) => {
-                    let delimiter = pm::Delimiter::from_internal(delim);
+                tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => {
+                    // We used to have an alternative behaviour for crates that
+                    // needed it: a hack used to pass AST fragments to
+                    // attribute and derive macros as a single nonterminal
+                    // token instead of a token stream. Such token needs to be
+                    // "unwrapped" and not represented as a delimited group. We
+                    // had a lint for a long time, but now we just emit a hard
+                    // error. Eventually we might remove the special case hard
+                    // error check altogether. See #73345.
+                    if let Delimiter::Invisible(InvisibleOrigin::MetaVar(kind)) = delim {
+                        crate::base::stream_pretty_printing_compatibility_hack(
+                            kind,
+                            &stream,
+                            rustc.psess(),
+                        );
+                    }
+
+                    // In `mk_delimited` we avoid nesting invisible delimited
+                    // of the same `MetaVarKind`. Here we do the same but
+                    // ignore the `MetaVarKind` because it is discarded when we
+                    // convert it to a `Group`.
+                    while let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim {
+                        if stream.len() == 1
+                            && let tree = stream.iter().next().unwrap()
+                            && let tokenstream::TokenTree::Delimited(_, _, delim2, stream2) = tree
+                            && let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim2
+                        {
+                            delim = *delim2;
+                            stream = stream2.clone();
+                        } else {
+                            break;
+                        }
+                    }
+
                     trees.push(TokenTree::Group(Group {
-                        delimiter,
-                        stream: Some(tts),
+                        delimiter: pm::Delimiter::from_internal(delim),
+                        stream: Some(stream),
                         span: DelimSpan {
                             open: span.open,
                             close: span.close,
@@ -279,15 +311,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
 
                 Interpolated(nt) => {
                     let stream = TokenStream::from_nonterminal_ast(&nt);
-                    // We used to have an alternative behaviour for crates that
-                    // needed it: a hack used to pass AST fragments to
-                    // attribute and derive macros as a single nonterminal
-                    // token instead of a token stream. Such token needs to be
-                    // "unwrapped" and not represented as a delimited group. We
-                    // had a lint for a long time, but now we just emit a hard
-                    // error. Eventually we might remove the special case hard
-                    // error check altogether. See #73345.
-                    crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess);
                     trees.push(TokenTree::Group(Group {
                         delimiter: pm::Delimiter::None,
                         stream: Some(stream),
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 0b034a2ae10..25764755a8f 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -15,7 +15,6 @@
 #![allow(internal_features)]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod accepted;
diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs
index 3ad51fa1e64..c6e0484b921 100644
--- a/compiler/rustc_fluent_macro/src/lib.rs
+++ b/compiler/rustc_fluent_macro/src/lib.rs
@@ -7,7 +7,6 @@
 #![feature(proc_macro_span)]
 #![feature(rustdoc_internals)]
 #![feature(track_path)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use proc_macro::TokenStream;
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index b5774f64b66..c8f8fd5be02 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -277,7 +277,6 @@
 )]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::borrow::Cow;
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index d4dfb9f2973..5cf231d5668 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3373,13 +3373,16 @@ pub struct OpaqueTy<'hir> {
     pub span: Span,
 }
 
-#[derive(Debug, Clone, Copy, HashStable_Generic)]
-pub enum PreciseCapturingArg<'hir> {
-    Lifetime(&'hir Lifetime),
+#[derive(Debug, Clone, Copy, HashStable_Generic, Encodable, Decodable)]
+pub enum PreciseCapturingArgKind<T, U> {
+    Lifetime(T),
     /// Non-lifetime argument (type or const)
-    Param(PreciseCapturingNonLifetimeArg),
+    Param(U),
 }
 
+pub type PreciseCapturingArg<'hir> =
+    PreciseCapturingArgKind<&'hir Lifetime, PreciseCapturingNonLifetimeArg>;
+
 impl PreciseCapturingArg<'_> {
     pub fn hir_id(self) -> HirId {
         match self {
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 270d4fbec30..4a839d40571 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,6 +4,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(closure_track_caller)]
@@ -13,7 +14,6 @@
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![feature(variant_count)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate self as rustc_hir;
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 8dc5d361750..a266286664c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -185,7 +185,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
 fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
+    let hir::OpaqueTy { origin, .. } = *tcx.hir_expect_opaque_ty(def_id);
 
     // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
     // `async-std` (and `pub async fn` in general).
@@ -785,7 +785,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             check_type_alias_type_params_are_used(tcx, def_id);
         }
         DefKind::ForeignMod => {
-            let it = tcx.hir().expect_item(def_id);
+            let it = tcx.hir_expect_item(def_id);
             let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
                 return;
             };
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 c193aad2afd..0a37a27b35b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1031,7 +1031,7 @@ fn report_trait_method_mismatch<'tcx>(
             // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
             // span points only at the type `Box<Self`>, but we want to cover the whole
             // argument pattern and type.
-            let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
+            let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
             let span = tcx
                 .hir_body_param_names(body)
                 .zip(sig.decl.inputs.iter())
@@ -1051,7 +1051,7 @@ fn report_trait_method_mismatch<'tcx>(
                 // Suggestion to change output type. We do not suggest in `async` functions
                 // to avoid complex logic or incorrect output.
                 if let ImplItemKind::Fn(sig, _) =
-                    &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind
+                    &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).kind
                     && !sig.header.asyncness.is_async()
                 {
                     let msg = "change the output type to match the trait";
@@ -1190,12 +1190,12 @@ fn extract_spans_for_error_reporting<'tcx>(
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
     let mut impl_args = {
-        let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
+        let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     };
 
     let trait_args = trait_m.def_id.as_local().map(|def_id| {
-        let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
+        let (sig, _) = tcx.hir_expect_trait_item(def_id).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     });
 
@@ -1371,7 +1371,7 @@ fn compare_number_of_generics<'tcx>(
                 spans
             };
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
-                let trait_item = tcx.hir().expect_trait_item(def_id);
+                let trait_item = tcx.hir_expect_trait_item(def_id);
                 let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
                 let impl_trait_spans: Vec<Span> = trait_item
                     .generics
@@ -1388,7 +1388,7 @@ fn compare_number_of_generics<'tcx>(
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
-            let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
+            let impl_item = tcx.hir_expect_impl_item(impl_.def_id.expect_local());
             let impl_item_impl_trait_spans: Vec<Span> = impl_item
                 .generics
                 .params
@@ -1466,7 +1466,7 @@ fn compare_number_of_method_arguments<'tcx>(
             .def_id
             .as_local()
             .and_then(|def_id| {
-                let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
+                let (trait_m_sig, _) = &tcx.hir_expect_trait_item(def_id).expect_fn();
                 let pos = trait_number_args.saturating_sub(1);
                 trait_m_sig.decl.inputs.get(pos).map(|arg| {
                     if pos == 0 {
@@ -1478,7 +1478,7 @@ fn compare_number_of_method_arguments<'tcx>(
             })
             .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 (impl_m_sig, _) = &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         let pos = impl_number_args.saturating_sub(1);
         let impl_span = impl_m_sig
             .decl
@@ -1580,10 +1580,10 @@ fn compare_synthetic_generics<'tcx>(
                     // as another generic argument
                     let new_name = tcx.opt_item_name(trait_def_id)?;
                     let trait_m = trait_m.def_id.as_local()?;
-                    let trait_m = tcx.hir().expect_trait_item(trait_m);
+                    let trait_m = tcx.hir_expect_trait_item(trait_m);
 
                     let impl_m = impl_m.def_id.as_local()?;
-                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+                    let impl_m = tcx.hir_expect_impl_item(impl_m);
 
                     // in case there are no generics, take the spot between the function name
                     // and the opening paren of the argument list
@@ -1613,7 +1613,7 @@ fn compare_synthetic_generics<'tcx>(
                 err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
                 let _: Option<_> = try {
                     let impl_m = impl_m.def_id.as_local()?;
-                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+                    let impl_m = tcx.hir_expect_impl_item(impl_m);
                     let (sig, _) = impl_m.expect_fn();
                     let input_tys = sig.decl.inputs;
 
@@ -1855,7 +1855,7 @@ fn compare_const_predicate_entailment<'tcx>(
         debug!(?impl_ty, ?trait_ty);
 
         // Locate the Span containing just the type of the offending impl
-        let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
+        let (ty, _) = tcx.hir_expect_impl_item(impl_ct_def_id).expect_const();
         cause.span = ty.span;
 
         let mut diag = struct_span_code_err!(
@@ -1868,7 +1868,7 @@ fn compare_const_predicate_entailment<'tcx>(
 
         let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
             // Add a label to the Span containing just the type of the const
-            let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
+            let (ty, _) = tcx.hir_expect_trait_item(trait_ct_def_id).expect_const();
             ty.span
         });
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9c28fac809d..b4a16b2b805 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -84,6 +84,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::print::with_types_for_signature;
 use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
@@ -240,11 +241,11 @@ fn missing_items_err(
         (Vec::new(), Vec::new(), Vec::new());
 
     for &trait_item in missing_items {
-        let snippet = suggestion_signature(
+        let snippet = with_types_for_signature!(suggestion_signature(
             tcx,
             trait_item,
             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) {
             missing_trait_item_label
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index a400aaa8142..fd5ffdc2d7a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -513,7 +513,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
             continue;
         }
 
-        let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id);
+        let gat_item_hir = tcx.hir_expect_trait_item(gat_def_id);
         debug!(?required_bounds);
         let param_env = tcx.param_env(gat_def_id);
 
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 750c09887a1..464ffa8711a 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -31,7 +31,7 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
         if used_trait_imports.contains(&id) {
             continue;
         }
-        let item = tcx.hir().expect_item(id);
+        let item = tcx.hir_expect_item(id);
         if item.span.is_dummy() {
             continue;
         }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index cee2f487639..c918abe4c07 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -82,7 +82,7 @@ fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaran
         _ => {}
     }
 
-    let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
+    let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
 
     Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }))
 }
@@ -109,7 +109,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
         Ok(()) => Ok(()),
         Err(CopyImplementationError::InfringingFields(fields)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
@@ -119,15 +119,15 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
             ))
         }
         Err(CopyImplementationError::NotAnAdt) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
         }
         Err(CopyImplementationError::HasDestructor) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
         }
         Err(CopyImplementationError::HasUnsafeFields) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx
                 .dcx()
                 .span_delayed_bug(span, format!("cannot implement `Copy` for `{}`", self_type)))
@@ -157,7 +157,7 @@ fn visit_implementation_of_const_param_ty(
     match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
         Ok(()) => Ok(()),
         Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
@@ -167,11 +167,11 @@ fn visit_implementation_of_const_param_ty(
             ))
         }
         Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
         }
         Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
@@ -181,7 +181,7 @@ fn visit_implementation_of_const_param_ty(
             ))
         }
         Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
         }
     }
@@ -526,7 +526,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
                     note: true,
                 }));
             } else if diff_fields.len() > 1 {
-                let item = tcx.hir().expect_item(impl_did);
+                let item = tcx.hir_expect_item(impl_did);
                 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(t), .. }) = &item.kind {
                     t.path.span
                 } else {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index dbf7a7378f5..0b7fc44460e 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -376,7 +376,7 @@ fn emit_orphan_check_error<'tcx>(
 ) -> ErrorGuaranteed {
     match err {
         traits::OrphanCheckErr::NonLocalInputType(tys) => {
-            let item = tcx.hir().expect_item(impl_def_id);
+            let item = tcx.hir_expect_item(impl_def_id);
             let impl_ = item.expect_impl();
             let hir_trait_ref = impl_.of_trait.as_ref().unwrap();
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 49523912b14..e0e435dd6f0 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -28,7 +28,7 @@ use rustc_errors::{
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
-use rustc_hir::{self as hir, GenericParamKind, HirId, Node};
+use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
@@ -469,8 +469,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
                     let item = self
                         .tcx
-                        .hir()
-                        .expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
+                        .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
                     match &item.kind {
                         hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Struct(_, generics)
@@ -1143,7 +1142,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
 
     let (is_alias, is_auto, safety, items) = match item.kind {
         hir::ItemKind::Trait(is_auto, safety, .., items) => {
@@ -1342,7 +1341,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
         ),
 
         ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
-            let abi = tcx.hir().get_foreign_abi(hir_id);
+            let abi = tcx.hir_get_foreign_abi(hir_id);
             compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
         }
 
@@ -1597,7 +1596,7 @@ pub fn suggest_impl_trait<'tcx>(
 
 fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     let impl_ = item.expect_impl();
     impl_.of_trait.as_ref().map(|ast_trait_ref| {
         let selfty = tcx.type_of(def_id).instantiate_identity();
@@ -1792,7 +1791,7 @@ fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueT
 fn rendered_precise_capturing_args<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> Option<&'tcx [Symbol]> {
+) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
     if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
         tcx.opt_rpitit_info(def_id.to_def_id())
     {
@@ -1801,7 +1800,12 @@ fn rendered_precise_capturing_args<'tcx>(
 
     tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
         hir::GenericBound::Use(args, ..) => {
-            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
+            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
+                PreciseCapturingArgKind::Lifetime(_) => {
+                    PreciseCapturingArgKind::Lifetime(arg.name())
+                }
+                PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
+            })))
         }
         _ => None,
     })
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 4debd3977f5..7cbd31de6ba 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -13,7 +13,7 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
     for id in tcx.hir_crate_items(()).opaques() {
         if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
         | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } =
-            tcx.hir().expect_opaque_ty(id).origin
+            tcx.hir_expect_opaque_ty(id).origin
             && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
             && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
         {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 6936544838c..16caa4f6874 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -480,5 +480,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) ->
             }
         }
     }
-    HasTait.visit_ty_unambig(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break()
+    HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().0).is_break()
 }
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 4dbdfa3d85a..78b20f9897c 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -404,11 +404,16 @@ fn check_constraints<'tcx>(
     };
 
     if let Some(local_sig_id) = sig_id.as_local()
-        && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
+        && tcx.hir_opt_delegation_sig_id(local_sig_id).is_some()
     {
         emit("recursive delegation is not supported yet");
     }
 
+    if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
+        // See issue #127443 for explanation.
+        emit("delegation to C-variadic functions is not allowed");
+    }
+
     ret
 }
 
@@ -416,7 +421,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> &'tcx [Ty<'tcx>] {
-    let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap();
+    let sig_id = tcx.hir_opt_delegation_sig_id(def_id).unwrap();
     let caller_sig = tcx.fn_sig(sig_id);
     if let Err(err) = check_constraints(tcx, def_id, sig_id) {
         let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
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 5f91f1d7b3e..8fff6eb9f6e 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     #[instrument(level = "debug", skip(self), ret)]
     pub fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {
         let tcx = self.tcx();
-        let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
+        let lifetime_name = |def_id| tcx.hir_name(tcx.local_def_id_to_hir_id(def_id));
 
         match resolved {
             rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 50b0e32b95e..cb3cdc5e8d3 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -59,6 +59,7 @@ This API is completely unstable and subject to change.
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -73,7 +74,6 @@ This API is completely unstable and subject to change.
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
 #![feature(unwrap_infallible)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 // These are used by Clippy.
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index ae624fc253f..3067766fb4d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -3,7 +3,6 @@
 
 // tidy-alphabetical-start
 #![recursion_limit = "256"]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::cell::Cell;
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 5e00161f693..2a24d626ac3 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -799,7 +799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Emit a different diagnostic for local variables, as they are not
                         // type definitions themselves, but rather variables *of* that type.
                         Res::Local(hir_id) => {
-                            err.arg("local_name", self.tcx.hir().name(hir_id));
+                            err.arg("local_name", self.tcx.hir_name(hir_id));
                             Some(fluent_generated::hir_typeck_invalid_local)
                         }
                         Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 70b49fea34f..5270c8ed356 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -32,6 +32,7 @@ use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
+use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_macros::{TypeFoldable, TypeVisitable};
@@ -155,7 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Debug)]
 enum CastError<'tcx> {
     ErrorGuaranteed(ErrorGuaranteed),
 
@@ -182,6 +183,7 @@ enum CastError<'tcx> {
     /// when we're typechecking a type parameter with a ?Sized bound.
     IntToWideCast(Option<&'static str>),
     ForeignNonExhaustiveAdt,
+    PtrPtrAddingAutoTrait(Vec<DefId>),
 }
 
 impl From<ErrorGuaranteed> for CastError<'_> {
@@ -596,6 +598,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 .with_note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
                 .emit();
             }
+            CastError::PtrPtrAddingAutoTrait(added) => {
+                fcx.dcx().emit_err(errors::PtrCastAddAutoToObject {
+                    span: self.span,
+                    traits_len: added.len(),
+                    traits: {
+                        let mut traits: Vec<_> = added
+                            .into_iter()
+                            .map(|trait_did| fcx.tcx.def_path_str(trait_did))
+                            .collect();
+
+                        traits.sort();
+                        traits.into()
+                    },
+                });
+            }
         }
     }
 
@@ -940,19 +957,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             .collect::<Vec<_>>();
 
                         if !added.is_empty() {
-                            tcx.dcx().emit_err(errors::PtrCastAddAutoToObject {
-                                span: self.span,
-                                traits_len: added.len(),
-                                traits: {
-                                    let mut traits: Vec<_> = added
-                                        .into_iter()
-                                        .map(|trait_did| tcx.def_path_str(trait_did))
-                                        .collect();
-
-                                    traits.sort();
-                                    traits.into()
-                                },
-                            });
+                            return Err(CastError::PtrPtrAddingAutoTrait(added));
                         }
 
                         Ok(CastKind::PtrPtrCast)
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 7e4026db738..7c6bb495be3 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -298,7 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Combine the diverging and has_error flags.
         self.diverges.set(self.diverges.get() | old_diverges);
 
-        debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id));
+        debug!("type of {} is...", self.tcx.hir_id_to_string(expr.hir_id));
         debug!("... {:?}, expected is {:?}", ty, expected);
 
         ty
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 9ff7eeb2368..63e4a8fb44b 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1235,7 +1235,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.cx.tainted_by_errors()?;
                 bug!(
                     "no type for node {} in mem_categorization",
-                    self.cx.tcx().hir().node_to_string(id)
+                    self.cx.tcx().hir_id_to_string(id)
                 );
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index da2d6579423..c82f7a91168 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(crate) fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> {
         self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
-            span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
+            span_bug!(span, "no type for local variable {}", self.tcx.hir_id_to_string(nid))
         })
     }
 
@@ -559,11 +559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(&t) => t,
             None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e),
             None => {
-                bug!(
-                    "no type for node {} in fcx {}",
-                    self.tcx.hir().node_to_string(id),
-                    self.tag()
-                );
+                bug!("no type for node {} in fcx {}", self.tcx.hir_id_to_string(id), self.tag());
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 35a3491f7c0..37aaaed5477 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -613,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .iter()
                     .take(4)
                     .map(|(var_hir_id, upvar)| {
-                        let var_name = self.tcx.hir().name(*var_hir_id).to_string();
+                        let var_name = self.tcx.hir_name(*var_hir_id).to_string();
                         let msg = format!("`{var_name}` captured here");
                         (upvar.span, msg)
                     })
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 8b9c2b4a6ca..4968998fd51 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -1,6 +1,7 @@
 // tidy-alphabetical-start
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(array_windows)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
@@ -8,7 +9,6 @@
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod _match;
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 69d7a6c97cb..72f8793d783 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -363,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let import_items: Vec<_> = applicable_trait
             .import_ids
             .iter()
-            .map(|&import_id| self.tcx.hir().expect_item(import_id))
+            .map(|&import_id| self.tcx.hir_expect_item(import_id))
             .collect();
 
         // Find an identifier with which this trait was imported (note that `_` doesn't count).
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index f87e5b5202a..ee01d78965d 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -2344,7 +2344,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             return false;
         };
         let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
-        let attrs = self.fcx.tcx.hir().attrs(hir_id);
+        let attrs = self.fcx.tcx.hir_attrs(hir_id);
         for attr in attrs {
             if sym::doc == attr.name_or_empty() {
             } else if sym::rustc_confusables == attr.name_or_empty() {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index cb1e89fb9e5..1a1540f505d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -791,7 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let Ok(pick) = self.lookup_probe_for_diagnostic(
                 item_name,
                 Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl),
-                self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
+                self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
                 ProbeScope::TraitsInScope,
                 None,
             )
@@ -834,8 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let SelfSource::MethodCall(rcvr_expr) = source {
             self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
-                let call_expr =
-                    self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
+                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
                 let probe = self.lookup_probe_for_diagnostic(
                     item_name,
                     output_ty,
@@ -2373,7 +2372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Applicability::MachineApplicable,
                     );
                 } else {
-                    let call_expr = tcx.hir().expect_expr(tcx.parent_hir_id(expr.hir_id));
+                    let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
 
                     if let Some(span) = call_expr.span.trim_start(item_name.span) {
                         err.span_suggestion(
@@ -2680,7 +2679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 mod_id,
                 expr.hir_id,
             ) {
-                let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
+                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(expr.hir_id));
 
                 let lang_items = self.tcx.lang_items();
                 let never_mention_traits = [
@@ -2757,7 +2756,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let SelfSource::MethodCall(expr) = source else {
             return;
         };
-        let call_expr = tcx.hir().expect_expr(tcx.parent_hir_id(expr.hir_id));
+        let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
 
         let ty::Adt(kind, args) = actual.kind() else {
             return;
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index f570d0d8a0d..37f3786c00a 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
                 base => bug!("Expected upvar, found={:?}", base),
             };
-            let var_ident = self.tcx.hir().ident(var_hir_id);
+            let var_ident = self.tcx.hir_ident(var_hir_id);
 
             let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
@@ -988,13 +988,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
                                     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),
+                                        self.tcx.hir_name(*var_hir_id),
                                         captured_name,
                                     ));
                                 }
                                 UpvarMigrationInfo::CapturingNothing { use_span } => {
                                     lint.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
-                                        self.tcx.hir().name(*var_hir_id),
+                                        self.tcx.hir_name(*var_hir_id),
                                     ));
                                 }
 
@@ -1009,13 +1009,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 match &lint_note.captures_info {
                                     UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
                                         lint.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
-                                            self.tcx.hir().name(*var_hir_id),
+                                            self.tcx.hir_name(*var_hir_id),
                                             captured_name,
                                         ));
                                     }
                                     UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
                                         lint.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
-                                            v = self.tcx.hir().name(*var_hir_id),
+                                            v = self.tcx.hir_name(*var_hir_id),
                                         ));
                                     }
                                 }
@@ -1026,7 +1026,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 // not capturing something anymore cannot cause a trait to fail to be implemented:
                                 match &lint_note.captures_info {
                                     UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
-                                        let var_name = self.tcx.hir().name(*var_hir_id);
+                                        let var_name = self.tcx.hir_name(*var_hir_id);
                                         lint.span_label(closure_head_span, format!("\
                                         in Rust 2018, this closure implements {missing_trait} \
                                         as `{var_name}` implements {missing_trait}, but in Rust 2021, \
@@ -2300,7 +2300,7 @@ fn construct_capture_info_string<'tcx>(
 }
 
 fn var_name(tcx: TyCtxt<'_>, var_hir_id: HirId) -> Symbol {
-    tcx.hir().name(var_hir_id)
+    tcx.hir_name(var_hir_id)
 }
 
 #[instrument(level = "debug", skip(tcx))]
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 8f2ca6babea..1b2056f541f 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -123,7 +123,7 @@ impl<'tcx> IfThisChanged<'tcx> {
     fn process_attrs(&mut self, def_id: LocalDefId) {
         let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
         let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
         for attr in attrs {
             if attr.has_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 563ed7614c6..dabfb6a90ca 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -2,12 +2,12 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![deny(missing_docs)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(file_buffered)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod assert_dep_graph;
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 3441a5f65c7..cc680838e7e 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -4,7 +4,6 @@
 #![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
 #![cfg_attr(feature = "nightly", feature(new_range_api))]
 #![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod bit_set;
diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs
index 67ec7761133..f0b58eabbff 100644
--- a/compiler/rustc_index_macros/src/newtype.rs
+++ b/compiler/rustc_index_macros/src/newtype.rs
@@ -305,7 +305,7 @@ impl Parse for Newtype {
     }
 }
 
-pub fn newtype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+pub(crate) fn newtype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let input = parse_macro_input!(input as Newtype);
     input.0.into()
 }
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index a04b2bb2b08..ece18f4ea64 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -24,7 +24,6 @@
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![recursion_limit = "512"] // For rustdoc
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod errors;
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index b35703d8e73..3f87b1a547b 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe;
 use rustc_query_impl::QueryCtxt;
 use rustc_query_system::query::print_query_stack;
 use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
-use rustc_session::filesearch::{self, sysroot_candidates};
+use rustc_session::filesearch::sysroot_candidates;
 use rustc_session::parse::ParseSess;
 use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
 use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
@@ -390,7 +390,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
 
     crate::callbacks::setup_callbacks();
 
-    let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
+    let sysroot = config.opts.sysroot.clone();
     let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot);
     let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
     let path_mapping = config.opts.file_path_mapping();
@@ -424,7 +424,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
 
             let bundle = match rustc_errors::fluent_bundle(
-                config.opts.maybe_sysroot.clone(),
+                config.opts.sysroot.clone(),
                 sysroot_candidates().to_vec(),
                 config.opts.unstable_opts.translate_lang.clone(),
                 config.opts.unstable_opts.translate_additional_ftl.as_deref(),
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 54cd341698f..67e0be93523 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod callbacks;
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 00600abb5f1..a2c1f1dbeda 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -8,7 +8,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut decls = None;
 
     for id in tcx.hir_free_items() {
-        let attrs = tcx.hir().attrs(id.hir_id());
+        let attrs = tcx.hir_attrs(id.hir_id());
         if attr::contains_name(attrs, sym::rustc_proc_macro_decls) {
             decls = Some(id.owner_id.def_id);
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index aabd235bcab..b44be1710ed 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -21,7 +21,7 @@ use rustc_session::config::{
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, filesearch, getopts};
+use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts};
 use rustc_span::edition::{DEFAULT_EDITION, Edition};
 use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
 use rustc_span::{FileName, SourceFileHashAlgorithm, sym};
@@ -41,7 +41,7 @@ where
 
     let matches = optgroups().parse(args).unwrap();
     let sessopts = build_session_options(&mut early_dcx, &matches);
-    let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
+    let sysroot = sessopts.sysroot.clone();
     let target =
         rustc_session::config::build_target_config(&early_dcx, &sessopts.target_triple, &sysroot);
     let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index bf18845a083..61638e45253 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -23,7 +23,6 @@
 // We want to be able to build this crate with a stable compiler,
 // so no `#![feature]` attributes should be added.
 #![deny(unstable_features)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod cursor;
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index f7be37dc4a2..918a42f3047 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -419,7 +419,7 @@ impl MissingDoc {
             return;
         }
 
-        let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
+        let attrs = cx.tcx.hir_attrs(cx.tcx.local_def_id_to_hir_id(def_id));
         let has_doc = attrs.iter().any(has_doc);
         if !has_doc {
             cx.emit_span_lint(
@@ -997,7 +997,7 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
 
 impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         let check_no_mangle_on_generic_fn = |no_mangle_attr: &hir::Attribute,
                                              impl_generics: Option<&hir::Generics<'_>>,
                                              generics: &hir::Generics<'_>,
@@ -1050,7 +1050,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                 for it in *items {
                     if let hir::AssocItemKind::Fn { .. } = it.kind {
                         if let Some(no_mangle_attr) =
-                            attr::find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle)
+                            attr::find_by_name(cx.tcx.hir_attrs(it.id.hir_id()), sym::no_mangle)
                         {
                             check_no_mangle_on_generic_fn(
                                 no_mangle_attr,
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 9ca148e1f25..4c2b82a9a23 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -38,7 +38,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
             }
             LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
                 // We are an `eval_always` query, so looking at the attribute's `AttrId` is ok.
-                let attr_id = tcx.hir().attrs(hir_id)[attr_index as usize].id();
+                let attr_id = tcx.hir_attrs(hir_id)[attr_index as usize].id();
 
                 (attr_id, lint_index)
             }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 23d6efa0508..852bb01c096 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -48,7 +48,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     where
         F: FnOnce(&mut Self),
     {
-        let attrs = self.context.tcx.hir().attrs(id);
+        let attrs = self.context.tcx.hir_attrs(id);
         let prev = self.context.last_node_with_lint_attrs;
         self.context.last_node_with_lint_attrs = id;
         debug!("late context: enter_attrs({:?})", attrs);
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 42b771471d0..8718fb807ec 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -152,7 +152,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
 #[instrument(level = "trace", skip(tcx), ret)]
 fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
     let store = unerased_lint_store(tcx.sess);
-    let attrs = tcx.hir_attrs(owner);
+    let attrs = tcx.hir_attr_map(owner);
 
     let mut levels = LintLevelsBuilder {
         sess: tcx.sess,
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 7018774e5c6..c38a7540018 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -21,6 +21,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
@@ -32,7 +33,6 @@
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod async_closures;
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 49f9ad39780..722779d3268 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -342,8 +342,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
         let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
             Some(Ident::from_str(name))
         } else {
-            ast::attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name)
-                .and_then(|attr| {
+            ast::attr::find_by_name(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
+                |attr| {
                     if let Attribute::Unparsed(n) = attr
                         && let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: lit }, .. } =
                             n.as_ref()
@@ -371,7 +371,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
                     } else {
                         None
                     }
-                })
+                },
+            )
         };
 
         if let Some(ident) = &crate_ident {
@@ -500,7 +501,7 @@ impl NonUpperCaseGlobals {
 
 impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         match it.kind {
             hir::ItemKind::Static(..) if !ast::attr::contains_name(attrs, sym::no_mangle) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index fcadbfc3c4a..6f3c32af5ef 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1589,7 +1589,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
     fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, it: &hir::ForeignItem<'tcx>) {
         let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Declaration };
-        let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
+        let abi = cx.tcx.hir_get_foreign_abi(it.hir_id());
 
         match it.kind {
             hir::ForeignItemKind::Fn(sig, _, _) => {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index e564235c41a..46b4b1d4383 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -1,7 +1,3 @@
-// tidy-alphabetical-start
-#![warn(unreachable_pub)]
-// tidy-alphabetical-end
-
 use rustc_abi::ExternAbi;
 use rustc_ast::AttrId;
 use rustc_ast::attr::AttributeExt;
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index bc3d4d6f83a..86f1bcc46ee 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1682,12 +1682,21 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
 #endif
 
   // Based on the 'InProcessThinBackend' constructor in LLVM
+#if LLVM_VERSION_GE(21, 0)
+  for (auto &Name : Data->Index.cfiFunctionDefs().symbols())
+    CfiFunctionDefs.insert(
+        GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
+  for (auto &Name : Data->Index.cfiFunctionDecls().symbols())
+    CfiFunctionDecls.insert(
+        GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
+#else
   for (auto &Name : Data->Index.cfiFunctionDefs())
     CfiFunctionDefs.insert(
         GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
   for (auto &Name : Data->Index.cfiFunctionDecls())
     CfiFunctionDecls.insert(
         GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
+#endif
 
 #if LLVM_VERSION_GE(20, 0)
   Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList,
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index eda9b2b1fc0..68058250a26 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -4,7 +4,6 @@
 #![doc(rust_logo)]
 #![feature(extern_types)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::cell::RefCell;
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 34fc0f00320..44ba064dd82 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -6,7 +6,6 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
 #![feature(proc_macro_tracked_env)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use proc_macro::TokenStream;
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 582c2215d92..be31aa629c8 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -84,7 +84,7 @@ pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
 fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     let sess = &tcx.sess;
 
-    if !sess.opts.output_types.should_codegen() {
+    if !sess.opts.output_types.should_link() {
         return IndexVec::new();
     }
 
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index ebcc0efd5a6..028d5c8b609 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -1,5 +1,6 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(coroutines)]
@@ -15,7 +16,6 @@
 #![feature(proc_macro_internals)]
 #![feature(rustdoc_internals)]
 #![feature(trusted_len)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate proc_macro;
@@ -35,8 +35,8 @@ pub mod locator;
 pub use creader::{DylibError, load_symbol_from_dylib};
 pub use fs::{METADATA_FILENAME, emit_wrapper_file};
 pub use native_libs::{
-    find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
-    walk_native_lib_search_dirs,
+    NativeLibSearchFallback, find_native_static_library, try_find_native_dynamic_library,
+    try_find_native_static_library, walk_native_lib_search_dirs,
 };
 pub use rmeta::{EncodedMetadata, METADATA_HEADER, encode_metadata, rendered_const};
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index b96921a63f3..1671b7e06b0 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -21,10 +21,17 @@ use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
 
 use crate::{errors, fluent_generated};
 
+/// The fallback directories are passed to linker, but not used when rustc does the search,
+/// because in the latter case the set of fallback directories cannot always be determined
+/// consistently at the moment.
+pub struct NativeLibSearchFallback<'a> {
+    pub self_contained_components: LinkSelfContainedComponents,
+    pub apple_sdk_root: Option<&'a Path>,
+}
+
 pub fn walk_native_lib_search_dirs<R>(
     sess: &Session,
-    self_contained_components: LinkSelfContainedComponents,
-    apple_sdk_root: Option<&Path>,
+    fallback: Option<NativeLibSearchFallback<'_>>,
     mut f: impl FnMut(&Path, bool /*is_framework*/) -> ControlFlow<R>,
 ) -> ControlFlow<R> {
     // Library search paths explicitly supplied by user (`-L` on the command line).
@@ -38,6 +45,11 @@ pub fn walk_native_lib_search_dirs<R>(
         }
     }
 
+    let Some(NativeLibSearchFallback { self_contained_components, apple_sdk_root }) = fallback
+    else {
+        return ControlFlow::Continue(());
+    };
+
     // The toolchain ships some native library components and self-contained linking was enabled.
     // Add the self-contained library directory to search paths.
     if self_contained_components.intersects(
@@ -93,23 +105,17 @@ pub fn try_find_native_static_library(
         if os == unix { vec![os] } else { vec![os, unix] }
     };
 
-    // FIXME: Account for self-contained linking settings and Apple SDK.
-    walk_native_lib_search_dirs(
-        sess,
-        LinkSelfContainedComponents::empty(),
-        None,
-        |dir, is_framework| {
-            if !is_framework {
-                for (prefix, suffix) in &formats {
-                    let test = dir.join(format!("{prefix}{name}{suffix}"));
-                    if test.exists() {
-                        return ControlFlow::Break(test);
-                    }
+    walk_native_lib_search_dirs(sess, None, |dir, is_framework| {
+        if !is_framework {
+            for (prefix, suffix) in &formats {
+                let test = dir.join(format!("{prefix}{name}{suffix}"));
+                if test.exists() {
+                    return ControlFlow::Break(test);
                 }
             }
-            ControlFlow::Continue(())
-        },
-    )
+        }
+        ControlFlow::Continue(())
+    })
     .break_value()
 }
 
@@ -132,22 +138,17 @@ pub fn try_find_native_dynamic_library(
         vec![os, meson, mingw]
     };
 
-    walk_native_lib_search_dirs(
-        sess,
-        LinkSelfContainedComponents::empty(),
-        None,
-        |dir, is_framework| {
-            if !is_framework {
-                for (prefix, suffix) in &formats {
-                    let test = dir.join(format!("{prefix}{name}{suffix}"));
-                    if test.exists() {
-                        return ControlFlow::Break(test);
-                    }
+    walk_native_lib_search_dirs(sess, None, |dir, is_framework| {
+        if !is_framework {
+            for (prefix, suffix) in &formats {
+                let test = dir.join(format!("{prefix}{name}{suffix}"));
+                if test.exists() {
+                    return ControlFlow::Break(test);
                 }
             }
-            ControlFlow::Continue(())
-        },
-    )
+        }
+        ControlFlow::Continue(())
+    })
     .break_value()
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 88a88847e6b..57c941976e4 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1357,8 +1357,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             features: &tcx.features(),
         };
         let attr_iter = tcx
-            .hir()
-            .attrs(tcx.local_def_id_to_hir_id(def_id))
+            .hir_attrs(tcx.local_def_id_to_hir_id(def_id))
             .iter()
             .filter(|attr| analyze_attr(*attr, &mut state));
 
@@ -1839,7 +1838,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx;
 
-        let hir::ItemKind::Macro(macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() };
+        let hir::ItemKind::Macro(macro_def, _) = tcx.hir_expect_item(def_id).kind else { bug!() };
         self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
         record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
     }
@@ -1918,11 +1917,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             for &proc_macro in &tcx.resolutions(()).proc_macros {
                 let id = proc_macro;
                 let proc_macro = tcx.local_def_id_to_hir_id(proc_macro);
-                let mut name = hir.name(proc_macro);
+                let mut name = tcx.hir_name(proc_macro);
                 let span = hir.span(proc_macro);
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
-                let attrs = hir.attrs(proc_macro);
+                let attrs = tcx.hir_attrs(proc_macro);
                 let macro_kind = if ast::attr::contains_name(attrs, sym::proc_macro) {
                     MacroKind::Bang
                 } else if ast::attr::contains_name(attrs, sym::proc_macro_attribute) {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 7b34e605c53..5536c93f84a 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -10,6 +10,7 @@ use rustc_abi::{FieldIdx, ReprOptions, VariantIdx};
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
+use rustc_hir::PreciseCapturingArgKind;
 use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId};
 use rustc_hir::definitions::DefKey;
@@ -440,7 +441,7 @@ define_tables! {
     coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
     mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
     rendered_const: Table<DefIndex, LazyValue<String>>,
-    rendered_precise_capturing_args: Table<DefIndex, LazyArray<Symbol>>,
+    rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
     asyncness: Table<DefIndex, ty::Asyncness>,
     fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
     coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index c85af81ee25..73c0af84a9f 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -275,7 +275,7 @@ impl<'tcx> TyCtxt<'tcx> {
             span_bug!(
                 self.hir().span(hir_id),
                 "body_owned_by: {} has no associated body",
-                self.hir().node_to_string(hir_id)
+                self.hir_id_to_string(hir_id)
             );
         })
     }
@@ -374,7 +374,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
     pub fn hir_krate_attrs(self) -> &'tcx [Attribute] {
-        self.hir().attrs(CRATE_HIR_ID)
+        self.hir_attrs(CRATE_HIR_ID)
     }
 
     pub fn hir_rustc_coherence_is_core(self) -> bool {
@@ -674,104 +674,178 @@ impl<'tcx> TyCtxt<'tcx> {
             }
         }
     }
-}
 
-impl<'hir> Map<'hir> {
-    pub fn get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
-        let parent = self.tcx.hir_get_parent_item(hir_id);
+    /// Get a representation of this `id` for debugging purposes.
+    /// NOTE: Do NOT use this in diagnostics!
+    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 node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
+
+        match self.hir_node(id) {
+            Node::Item(item) => {
+                let item_str = match item.kind {
+                    ItemKind::ExternCrate(..) => "extern crate",
+                    ItemKind::Use(..) => "use",
+                    ItemKind::Static(..) => "static",
+                    ItemKind::Const(..) => "const",
+                    ItemKind::Fn { .. } => "fn",
+                    ItemKind::Macro(..) => "macro",
+                    ItemKind::Mod(..) => "mod",
+                    ItemKind::ForeignMod { .. } => "foreign mod",
+                    ItemKind::GlobalAsm { .. } => "global asm",
+                    ItemKind::TyAlias(..) => "ty",
+                    ItemKind::Enum(..) => "enum",
+                    ItemKind::Struct(..) => "struct",
+                    ItemKind::Union(..) => "union",
+                    ItemKind::Trait(..) => "trait",
+                    ItemKind::TraitAlias(..) => "trait alias",
+                    ItemKind::Impl { .. } => "impl",
+                };
+                format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
+            }
+            Node::ForeignItem(item) => {
+                format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
+            }
+            Node::ImplItem(ii) => {
+                let kind = match ii.kind {
+                    ImplItemKind::Const(..) => "associated constant",
+                    ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                        ImplicitSelfKind::None => "associated function",
+                        _ => "method",
+                    },
+                    ImplItemKind::Type(_) => "associated type",
+                };
+                format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
+            }
+            Node::TraitItem(ti) => {
+                let kind = match ti.kind {
+                    TraitItemKind::Const(..) => "associated constant",
+                    TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                        ImplicitSelfKind::None => "associated function",
+                        _ => "trait method",
+                    },
+                    TraitItemKind::Type(..) => "associated type",
+                };
+
+                format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
+            }
+            Node::Variant(variant) => {
+                format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
+            }
+            Node::Field(field) => {
+                format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
+            }
+            Node::AnonConst(_) => node_str("const"),
+            Node::ConstBlock(_) => node_str("const"),
+            Node::ConstArg(_) => node_str("const"),
+            Node::Expr(_) => node_str("expr"),
+            Node::ExprField(_) => node_str("expr field"),
+            Node::Stmt(_) => node_str("stmt"),
+            Node::PathSegment(_) => node_str("path segment"),
+            Node::Ty(_) => node_str("type"),
+            Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
+            Node::TraitRef(_) => node_str("trait ref"),
+            Node::OpaqueTy(_) => node_str("opaque type"),
+            Node::Pat(_) => node_str("pat"),
+            Node::TyPat(_) => node_str("pat ty"),
+            Node::PatField(_) => node_str("pattern field"),
+            Node::PatExpr(_) => node_str("pattern literal"),
+            Node::Param(_) => node_str("param"),
+            Node::Arm(_) => node_str("arm"),
+            Node::Block(_) => node_str("block"),
+            Node::Infer(_) => node_str("infer"),
+            Node::LetStmt(_) => node_str("local"),
+            Node::Ctor(ctor) => format!(
+                "{id} (ctor {})",
+                ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
+            ),
+            Node::Lifetime(_) => node_str("lifetime"),
+            Node::GenericParam(param) => {
+                format!("{id} (generic_param {})", path_str(param.def_id))
+            }
+            Node::Crate(..) => String::from("(root_crate)"),
+            Node::WherePredicate(_) => node_str("where predicate"),
+            Node::Synthetic => unreachable!(),
+            Node::Err(_) => node_str("error"),
+            Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
+        }
+    }
+
+    pub fn hir_get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
+        let parent = self.hir_get_parent_item(hir_id);
         if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) =
-            self.tcx.hir_owner_node(parent)
+            self.hir_owner_node(parent)
         {
             return *abi;
         }
         bug!(
             "expected foreign mod or inlined parent, found {}",
-            self.node_to_string(HirId::make_owner(parent.def_id))
+            self.hir_id_to_string(HirId::make_owner(parent.def_id))
         )
     }
 
-    pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_item(self, id: LocalDefId) -> &'tcx Item<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::Item(item) => item,
-            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
+            _ => bug!("expected item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_impl_item(self, id: LocalDefId) -> &'tcx ImplItem<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::ImplItem(item) => item,
-            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
+            _ => bug!("expected impl item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_trait_item(self, id: LocalDefId) -> &'tcx TraitItem<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::TraitItem(item) => item,
-            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
-        }
-    }
-
-    pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
-        Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output)
-    }
-
-    pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Variant(variant) => variant,
-            _ => bug!("expected variant, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Field(field) => field,
-            _ => bug!("expected field, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
-        match self.tcx.hir_owner_node(id) {
-            OwnerNode::ForeignItem(item) => item,
             _ => {
-                bug!(
-                    "expected foreign item, found {}",
-                    self.node_to_string(HirId::make_owner(id.def_id))
-                )
+                bug!("expected trait item, found {}", self.hir_id_to_string(HirId::make_owner(id)))
             }
         }
     }
 
+    pub fn hir_get_fn_output(self, def_id: LocalDefId) -> Option<&'tcx FnRetTy<'tcx>> {
+        Some(&self.opt_hir_owner_node(def_id)?.fn_decl()?.output)
+    }
+
     #[track_caller]
-    pub fn expect_opaque_ty(self, id: LocalDefId) -> &'hir OpaqueTy<'hir> {
-        match self.tcx.hir_node_by_def_id(id) {
+    pub fn hir_expect_opaque_ty(self, id: LocalDefId) -> &'tcx OpaqueTy<'tcx> {
+        match self.hir_node_by_def_id(id) {
             Node::OpaqueTy(opaq) => opaq,
             _ => {
                 bug!(
                     "expected opaque type definition, found {}",
-                    self.node_to_string(self.tcx.local_def_id_to_hir_id(id))
+                    self.hir_id_to_string(self.local_def_id_to_hir_id(id))
                 )
             }
         }
     }
 
-    pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
-        match self.tcx.hir_node(id) {
+    pub fn hir_expect_expr(self, id: HirId) -> &'tcx Expr<'tcx> {
+        match self.hir_node(id) {
             Node::Expr(expr) => expr,
-            _ => bug!("expected expr, found {}", self.node_to_string(id)),
+            _ => bug!("expected expr, found {}", self.hir_id_to_string(id)),
         }
     }
 
-    pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
-        self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
+    pub fn hir_opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
+        self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
     }
 
     #[inline]
-    fn opt_ident(self, id: HirId) -> Option<Ident> {
-        match self.tcx.hir_node(id) {
+    fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
+        match self.hir_node(id) {
             Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
             // A `Ctor` doesn't have an identifier itself, but its parent
             // struct/variant does. Compare with `hir::Map::span`.
-            Node::Ctor(..) => match self.tcx.parent_hir_node(id) {
+            Node::Ctor(..) => match self.parent_hir_node(id) {
                 Node::Item(item) => Some(item.ident),
                 Node::Variant(variant) => Some(variant.ident),
                 _ => unreachable!(),
@@ -781,30 +855,32 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
-    pub(super) fn opt_ident_span(self, id: HirId) -> Option<Span> {
-        self.opt_ident(id).map(|ident| ident.span)
+    pub(super) fn hir_opt_ident_span(self, id: HirId) -> Option<Span> {
+        self.hir_opt_ident(id).map(|ident| ident.span)
     }
 
     #[inline]
-    pub fn ident(self, id: HirId) -> Ident {
-        self.opt_ident(id).unwrap()
+    pub fn hir_ident(self, id: HirId) -> Ident {
+        self.hir_opt_ident(id).unwrap()
     }
 
     #[inline]
-    pub fn opt_name(self, id: HirId) -> Option<Symbol> {
-        self.opt_ident(id).map(|ident| ident.name)
+    pub fn hir_opt_name(self, id: HirId) -> Option<Symbol> {
+        self.hir_opt_ident(id).map(|ident| ident.name)
     }
 
-    pub fn name(self, id: HirId) -> Symbol {
-        self.opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.node_to_string(id)))
+    pub fn hir_name(self, id: HirId) -> Symbol {
+        self.hir_opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.hir_id_to_string(id)))
     }
 
     /// Given a node ID, gets a list of attributes associated with the AST
     /// corresponding to the node-ID.
-    pub fn attrs(self, id: HirId) -> &'hir [Attribute] {
-        self.tcx.hir_attrs(id.owner).get(id.local_id)
+    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 {
@@ -977,12 +1053,6 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    /// Get a representation of this `id` for debugging purposes.
-    /// NOTE: Do NOT use this in diagnostics!
-    pub fn node_to_string(self, id: HirId) -> String {
-        hir_id_to_string(self, 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> {
@@ -1147,102 +1217,6 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
     upstream_crates
 }
 
-fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
-    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id);
-
-    let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
-    let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
-
-    match map.tcx.hir_node(id) {
-        Node::Item(item) => {
-            let item_str = match item.kind {
-                ItemKind::ExternCrate(..) => "extern crate",
-                ItemKind::Use(..) => "use",
-                ItemKind::Static(..) => "static",
-                ItemKind::Const(..) => "const",
-                ItemKind::Fn { .. } => "fn",
-                ItemKind::Macro(..) => "macro",
-                ItemKind::Mod(..) => "mod",
-                ItemKind::ForeignMod { .. } => "foreign mod",
-                ItemKind::GlobalAsm { .. } => "global asm",
-                ItemKind::TyAlias(..) => "ty",
-                ItemKind::Enum(..) => "enum",
-                ItemKind::Struct(..) => "struct",
-                ItemKind::Union(..) => "union",
-                ItemKind::Trait(..) => "trait",
-                ItemKind::TraitAlias(..) => "trait alias",
-                ItemKind::Impl { .. } => "impl",
-            };
-            format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
-        }
-        Node::ForeignItem(item) => {
-            format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
-        }
-        Node::ImplItem(ii) => {
-            let kind = match ii.kind {
-                ImplItemKind::Const(..) => "associated constant",
-                ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "method",
-                },
-                ImplItemKind::Type(_) => "associated type",
-            };
-            format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
-        }
-        Node::TraitItem(ti) => {
-            let kind = match ti.kind {
-                TraitItemKind::Const(..) => "associated constant",
-                TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "trait method",
-                },
-                TraitItemKind::Type(..) => "associated type",
-            };
-
-            format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
-        }
-        Node::Variant(variant) => {
-            format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
-        }
-        Node::Field(field) => {
-            format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
-        }
-        Node::AnonConst(_) => node_str("const"),
-        Node::ConstBlock(_) => node_str("const"),
-        Node::ConstArg(_) => node_str("const"),
-        Node::Expr(_) => node_str("expr"),
-        Node::ExprField(_) => node_str("expr field"),
-        Node::Stmt(_) => node_str("stmt"),
-        Node::PathSegment(_) => node_str("path segment"),
-        Node::Ty(_) => node_str("type"),
-        Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
-        Node::TraitRef(_) => node_str("trait ref"),
-        Node::OpaqueTy(_) => node_str("opaque type"),
-        Node::Pat(_) => node_str("pat"),
-        Node::TyPat(_) => node_str("pat ty"),
-        Node::PatField(_) => node_str("pattern field"),
-        Node::PatExpr(_) => node_str("pattern literal"),
-        Node::Param(_) => node_str("param"),
-        Node::Arm(_) => node_str("arm"),
-        Node::Block(_) => node_str("block"),
-        Node::Infer(_) => node_str("infer"),
-        Node::LetStmt(_) => node_str("local"),
-        Node::Ctor(ctor) => format!(
-            "{id} (ctor {})",
-            ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
-        ),
-        Node::Lifetime(_) => node_str("lifetime"),
-        Node::GenericParam(param) => {
-            format!("{id} (generic_param {})", path_str(param.def_id))
-        }
-        Node::Crate(..) => String::from("(root_crate)"),
-        Node::WherePredicate(_) => node_str("where predicate"),
-        Node::Synthetic => unreachable!(),
-        Node::Err(_) => node_str("error"),
-        Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
-    }
-}
-
 pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
     let mut collector = ItemCollector::new(tcx, false);
 
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 6071a58367e..68b9a4f56b9 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -202,13 +202,13 @@ pub fn provide(providers: &mut Providers) {
             }
         })
     };
-    providers.hir_attrs = |tcx, id| {
+    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_ident_span = |tcx, def_id| {
         let hir_id = tcx.local_def_id_to_hir_id(def_id);
-        tcx.hir().opt_ident_span(hir_id)
+        tcx.hir_opt_ident_span(hir_id)
     };
     providers.fn_arg_names = |tcx, def_id| {
         let hir = tcx.hir();
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 48ea7df5c23..1e6178144c9 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -29,6 +29,7 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::potential_query_instability)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(allocator_api)]
@@ -61,7 +62,6 @@
 #![feature(try_trait_v2_yeet)]
 #![feature(type_alias_impl_trait)]
 #![feature(yeet_expr)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 #[cfg(test)]
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index b24f6bc7770..aed38414ab1 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -15,7 +15,9 @@ use provenance_map::*;
 use rustc_abi::{Align, HasDataLayout, Size};
 use rustc_ast::Mutability;
 use rustc_data_structures::intern::Interned;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use rustc_macros::HashStable;
+use rustc_serialize::{Decodable, Encodable};
+use rustc_type_ir::{TyDecoder, TyEncoder};
 
 use super::{
     AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer,
@@ -77,7 +79,7 @@ impl AllocBytes for Box<[u8]> {
 /// module provides higher-level access.
 // Note: for performance reasons when interning, some of the `Allocation` fields can be partially
 // hashed. (see the `Hash` impl below for more details), so the impl is not derived.
-#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
+#[derive(Clone, Eq, PartialEq)]
 #[derive(HashStable)]
 pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box<[u8]>> {
     /// The actual bytes of the allocation.
@@ -101,6 +103,117 @@ pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box
     pub extra: Extra,
 }
 
+/// Helper struct that packs an alignment, mutability, and "all bytes are zero" flag together.
+///
+/// Alignment values always have 2 free high bits, and we check for this in our [`Encodable`] impl.
+struct AllocFlags {
+    align: Align,
+    mutability: Mutability,
+    all_zero: bool,
+}
+
+impl<E: TyEncoder> Encodable<E> for AllocFlags {
+    fn encode(&self, encoder: &mut E) {
+        // Make sure Align::MAX can be stored with the high 2 bits unset.
+        const {
+            let max_supported_align_repr = u8::MAX >> 2;
+            let max_supported_align = 1 << max_supported_align_repr;
+            assert!(Align::MAX.bytes() <= max_supported_align)
+        }
+
+        let mut flags = self.align.bytes().trailing_zeros() as u8;
+        flags |= match self.mutability {
+            Mutability::Not => 0,
+            Mutability::Mut => 1 << 6,
+        };
+        flags |= (self.all_zero as u8) << 7;
+        flags.encode(encoder);
+    }
+}
+
+impl<D: TyDecoder> Decodable<D> for AllocFlags {
+    fn decode(decoder: &mut D) -> Self {
+        let flags: u8 = Decodable::decode(decoder);
+        let align = flags & 0b0011_1111;
+        let mutability = flags & 0b0100_0000;
+        let all_zero = flags & 0b1000_0000;
+
+        let align = Align::from_bytes(1 << align).unwrap();
+        let mutability = match mutability {
+            0 => Mutability::Not,
+            _ => Mutability::Mut,
+        };
+        let all_zero = all_zero > 0;
+
+        AllocFlags { align, mutability, all_zero }
+    }
+}
+
+/// Efficiently detect whether a slice of `u8` is all zero.
+///
+/// This is used in encoding of [`Allocation`] to special-case all-zero allocations. It is only
+/// optimized a little, because for many allocations the encoding of the actual bytes does not
+/// dominate runtime.
+#[inline]
+fn all_zero(buf: &[u8]) -> bool {
+    // In the empty case we wouldn't encode any contents even without this system where we
+    // special-case allocations whose contents are all 0. We can return anything in the empty case.
+    if buf.is_empty() {
+        return true;
+    }
+    // Just fast-rejecting based on the first element significantly reduces the amount that we end
+    // up walking the whole array.
+    if buf[0] != 0 {
+        return false;
+    }
+
+    // This strategy of combining all slice elements with & or | is unbeatable for the large
+    // all-zero case because it is so well-understood by autovectorization.
+    buf.iter().fold(true, |acc, b| acc & (*b == 0))
+}
+
+/// Custom encoder for [`Allocation`] to more efficiently represent the case where all bytes are 0.
+impl<Prov: Provenance, Extra, Bytes, E: TyEncoder> Encodable<E> for Allocation<Prov, Extra, Bytes>
+where
+    Bytes: AllocBytes,
+    ProvenanceMap<Prov>: Encodable<E>,
+    Extra: Encodable<E>,
+{
+    fn encode(&self, encoder: &mut E) {
+        let all_zero = all_zero(&self.bytes);
+        AllocFlags { align: self.align, mutability: self.mutability, all_zero }.encode(encoder);
+
+        encoder.emit_usize(self.bytes.len());
+        if !all_zero {
+            encoder.emit_raw_bytes(&self.bytes);
+        }
+        self.provenance.encode(encoder);
+        self.init_mask.encode(encoder);
+        self.extra.encode(encoder);
+    }
+}
+
+impl<Prov: Provenance, Extra, Bytes, D: TyDecoder> Decodable<D> for Allocation<Prov, Extra, Bytes>
+where
+    Bytes: AllocBytes,
+    ProvenanceMap<Prov>: Decodable<D>,
+    Extra: Decodable<D>,
+{
+    fn decode(decoder: &mut D) -> Self {
+        let AllocFlags { align, mutability, all_zero } = Decodable::decode(decoder);
+
+        let len = decoder.read_usize();
+        let bytes = if all_zero { vec![0u8; len] } else { decoder.read_raw_bytes(len).to_vec() };
+        let bytes = Bytes::from_bytes(bytes, align);
+
+        let provenance = Decodable::decode(decoder);
+        let init_mask = Decodable::decode(decoder);
+        let extra = Decodable::decode(decoder);
+
+        Self { bytes, provenance, init_mask, align, mutability, extra }
+    }
+}
+
 /// This is the maximum size we will hash at a time, when interning an `Allocation` and its
 /// `InitMask`. Note, we hash that amount of bytes twice: at the start, and at the end of a buffer.
 /// Used when these two structures are large: we only partially hash the larger fields in that
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 2675b7e0fc5..effedf854e4 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -452,12 +452,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
         let id = self.alloc_map.reserve();
         debug!("creating alloc {:?} with id {id:?}", alloc_salt.0);
-        let had_previous = self
-            .alloc_map
-            .to_alloc
-            .lock_shard_by_value(&id)
-            .insert(id, alloc_salt.0.clone())
-            .is_some();
+        let had_previous = self.alloc_map.to_alloc.insert(id, alloc_salt.0.clone()).is_some();
         // We just reserved, so should always be unique.
         assert!(!had_previous);
         dedup.insert(alloc_salt, id);
@@ -510,7 +505,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// local dangling pointers and allocations in constants/statics.
     #[inline]
     pub fn try_get_global_alloc(self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
-        self.alloc_map.to_alloc.lock_shard_by_value(&id).get(&id).cloned()
+        self.alloc_map.to_alloc.get(&id)
     }
 
     #[inline]
@@ -529,9 +524,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
     pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
-        if let Some(old) =
-            self.alloc_map.to_alloc.lock_shard_by_value(&id).insert(id, GlobalAlloc::Memory(mem))
-        {
+        if let Some(old) = self.alloc_map.to_alloc.insert(id, GlobalAlloc::Memory(mem)) {
             bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
         }
     }
@@ -539,11 +532,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to
     /// call this function twice, even with the same `DefId` will ICE the compiler.
     pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) {
-        if let Some(old) = self
-            .alloc_map
-            .to_alloc
-            .lock_shard_by_value(&id)
-            .insert(id, GlobalAlloc::Static(def_id.to_def_id()))
+        if let Some(old) =
+            self.alloc_map.to_alloc.insert(id, GlobalAlloc::Static(def_id.to_def_id()))
         {
             bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
         }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f880b1364c2..573f7895da2 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -653,7 +653,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
             write!(w, "static mut ")?
         }
         (_, _) if is_function => write!(w, "fn ")?,
-        (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
+        // things like anon const, not an item
+        (DefKind::AnonConst | DefKind::InlineConst, _) => {}
+        // `global_asm!` have fake bodies, which we may dump after mir-build
+        (DefKind::GlobalAsm, _) => {}
         _ => bug!("Unexpected def kind {:?}", kind),
     }
 
@@ -1200,7 +1203,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
                         {
                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                let var_name = tcx.hir().name(var_id);
+                                let var_name = tcx.hir_name(var_id);
                                 struct_fmt.field(var_name.as_str(), place);
                             }
                         } else {
@@ -1221,7 +1224,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
                         {
                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                let var_name = tcx.hir().name(var_id);
+                                let var_name = tcx.hir_name(var_id);
                                 struct_fmt.field(var_name.as_str(), place);
                             }
                         } else {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c8708857565..94a5a3769a3 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -25,7 +25,7 @@ use rustc_hir::def_id::{
     CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
 };
 use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate};
+use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
 use rustc_index::IndexVec;
 use rustc_lint_defs::LintId;
 use rustc_macros::rustc_queries;
@@ -198,7 +198,7 @@ rustc_queries! {
     ///
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
-    query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
+    query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
         desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) }
         feedable
     }
@@ -1424,7 +1424,7 @@ rustc_queries! {
     }
 
     /// Gets the rendered precise capturing args for an opaque for use in rustdoc.
-    query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> {
+    query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
         desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 53f233f20eb..7e6151745e2 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -980,12 +980,9 @@ pub enum CodegenObligationError {
     /// overflow bug, since I believe this is the only case
     /// where ambiguity can result.
     Ambiguity,
-    /// This can trigger when we probe for the source of a `'static` lifetime requirement
-    /// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
-    /// This can also trigger when we have a global bound that is not actually satisfied,
-    /// but was included during typeck due to the trivial_bounds feature.
+    /// This can trigger when we have a global bound that is not actually satisfied
+    /// due to trivial bounds.
     Unimplemented,
-    FulfillmentError,
     /// The selected impl has unconstrained generic parameters. This will emit an error
     /// during impl WF checking.
     UnconstrainedParam(ErrorGuaranteed),
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index 9ce5373b031..8e54a9d487d 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -72,7 +72,7 @@ impl OverlapMode {
                     .as_local()
                     .into_iter()
                     .flat_map(|local_def_id| {
-                        tcx.hir().attrs(tcx.local_def_id_to_hir_id(local_def_id))
+                        tcx.hir_attrs(tcx.local_def_id_to_hir_id(local_def_id))
                     })
                     .find(|attr| attr.has_name(sym::rustc_strict_coherence))
                     .map(|attr| attr.span());
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 5d9b1ddfa38..703b6ce9247 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -296,7 +296,7 @@ pub struct CaptureInfo {
 
 pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
     let mut curr_string: String = match place.base {
-        HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
+        HirPlaceBase::Upvar(upvar_id) => tcx.hir_name(upvar_id.var_path.hir_id).to_string(),
         _ => bug!("Capture_information should only contain upvars"),
     };
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index edba2a2530f..a2472157d0e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1299,7 +1299,7 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
             ),
             bodies,
         })));
-        self.feed_owner_id().hir_attrs(attrs);
+        self.feed_owner_id().hir_attr_map(attrs);
     }
 }
 
@@ -2214,7 +2214,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the origin of the opaque type `def_id`.
     #[instrument(skip(self), level = "trace", ret)]
     pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
-        self.hir().expect_opaque_ty(def_id).origin
+        self.hir_expect_opaque_ty(def_id).origin
     }
 
     pub fn finish(self) {
@@ -2336,8 +2336,8 @@ macro_rules! sty_debug_print {
                 $(let mut $variant = total;)*
 
                 for shard in tcx.interners.type_.lock_shards() {
-                    let types = shard.keys();
-                    for &InternedInSet(t) in types {
+                    let types = shard.iter();
+                    for &(InternedInSet(t), ()) in types {
                         let variant = match t.internee {
                             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                                 ty::Float(..) | ty::Str | ty::Never => continue,
@@ -3118,9 +3118,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
         self.mk_bound_variable_kinds(
-            &self.late_bound_vars_map(id.owner).get(&id.local_id).cloned().unwrap_or_else(|| {
-                bug!("No bound vars found for {}", self.hir().node_to_string(id))
-            }),
+            &self
+                .late_bound_vars_map(id.owner)
+                .get(&id.local_id)
+                .cloned()
+                .unwrap_or_else(|| bug!("No bound vars found for {}", self.hir_id_to_string(id))),
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 97cfe5946af..ad9d32fd6c1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1696,7 +1696,7 @@ impl<'tcx> TyCtxt<'tcx> {
     // FIXME(@lcnr): Remove this function.
     pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [hir::Attribute] {
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did))
+            self.hir_attrs(self.local_def_id_to_hir_id(did))
         } else {
             self.attrs_for_def(did)
         }
@@ -1720,7 +1720,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> impl Iterator<Item = &'tcx hir::Attribute> {
         let did: DefId = did.into();
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did)).iter()
+            self.hir_attrs(self.local_def_id_to_hir_id(did)).iter()
         } else {
             self.attrs_for_def(did).iter()
         }
@@ -1764,7 +1764,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> impl Iterator<Item = &'tcx hir::Attribute> {
         let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr);
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
+            self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
         } else {
             self.attrs_for_def(did).iter().filter(filter_fn)
         }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 71fc38cb7ed..19e2b574563 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -3,6 +3,7 @@ use std::hash::Hash;
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir::def_id::DefIndex;
 use rustc_index::{Idx, IndexVec};
+use rustc_span::Symbol;
 
 use crate::ty;
 
@@ -96,6 +97,7 @@ trivially_parameterized_over_tcx! {
     rustc_hir::def_id::DefIndex,
     rustc_hir::definitions::DefKey,
     rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
+    rustc_hir::PreciseCapturingArgKind<Symbol, Symbol>,
     rustc_index::bit_set::DenseBitSet<u32>,
     rustc_index::bit_set::FiniteBitSet<u32>,
     rustc_session::cstore::ForeignModule,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2a3a7705b7b..72924c0dd4b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -63,6 +63,18 @@ thread_local! {
     static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
     static REDUCED_QUERIES: Cell<bool> = const { Cell::new(false) };
     static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
+    static RTN_MODE: Cell<RtnMode> = const { Cell::new(RtnMode::ForDiagnostic) };
+}
+
+/// Rendering style for RTN types.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum RtnMode {
+    /// Print the RTN type as an impl trait with its path, i.e.e `impl Sized { T::method(..) }`.
+    ForDiagnostic,
+    /// Print the RTN type as an impl trait, i.e. `impl Sized`.
+    ForSignature,
+    /// Print the RTN type as a value path, i.e. `T::method(..): ...`.
+    ForSuggestion,
 }
 
 macro_rules! define_helper {
@@ -124,6 +136,38 @@ define_helper!(
     fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
 );
 
+#[must_use]
+pub struct RtnModeHelper(RtnMode);
+
+impl RtnModeHelper {
+    pub fn with(mode: RtnMode) -> RtnModeHelper {
+        RtnModeHelper(RTN_MODE.with(|c| c.replace(mode)))
+    }
+}
+
+impl Drop for RtnModeHelper {
+    fn drop(&mut self) {
+        RTN_MODE.with(|c| c.set(self.0))
+    }
+}
+
+/// Print types for the purposes of a suggestion.
+///
+/// Specifically, this will render RPITITs as `T::method(..)` which is suitable for
+/// things like where-clauses.
+pub macro with_types_for_suggestion($e:expr) {{
+    let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion);
+    $e
+}}
+
+/// Print types for the purposes of a signature suggestion.
+///
+/// Specifically, this will render RPITITs as `impl Trait` rather than `T::method(..)`.
+pub macro with_types_for_signature($e:expr) {{
+    let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSignature);
+    $e
+}}
+
 /// Avoids running any queries during prints.
 pub macro with_no_queries($e:expr) {{
     $crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!(
@@ -1223,22 +1267,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
         }
 
-        if self.tcx().features().return_type_notation()
-            && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
-                self.tcx().opt_rpitit_info(def_id)
-            && let ty::Alias(_, alias_ty) =
-                self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
-            && alias_ty.def_id == def_id
-            && let generics = self.tcx().generics_of(fn_def_id)
-            // FIXME(return_type_notation): We only support lifetime params for now.
-            && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
-        {
-            let num_args = generics.count();
-            write!(self, " {{ ")?;
-            self.print_def_path(fn_def_id, &args[..num_args])?;
-            write!(self, "(..) }}")?;
-        }
-
         Ok(())
     }
 
@@ -1306,6 +1334,46 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         )
     }
 
+    fn pretty_print_rpitit(
+        &mut self,
+        def_id: DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> Result<(), PrintError> {
+        let fn_args = if self.tcx().features().return_type_notation()
+            && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
+                self.tcx().opt_rpitit_info(def_id)
+            && let ty::Alias(_, alias_ty) =
+                self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
+            && alias_ty.def_id == def_id
+            && let generics = self.tcx().generics_of(fn_def_id)
+            // FIXME(return_type_notation): We only support lifetime params for now.
+            && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
+        {
+            let num_args = generics.count();
+            Some((fn_def_id, &args[..num_args]))
+        } else {
+            None
+        };
+
+        match (fn_args, RTN_MODE.with(|c| c.get())) {
+            (Some((fn_def_id, fn_args)), RtnMode::ForDiagnostic) => {
+                self.pretty_print_opaque_impl_type(def_id, args)?;
+                write!(self, " {{ ")?;
+                self.print_def_path(fn_def_id, fn_args)?;
+                write!(self, "(..) }}")?;
+            }
+            (Some((fn_def_id, fn_args)), RtnMode::ForSuggestion) => {
+                self.print_def_path(fn_def_id, fn_args)?;
+                write!(self, "(..)")?;
+            }
+            _ => {
+                self.pretty_print_opaque_impl_type(def_id, args)?;
+            }
+        }
+
+        Ok(())
+    }
+
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
         None
     }
@@ -3123,22 +3191,21 @@ define_print! {
     ty::AliasTerm<'tcx> {
         match self.kind(cx.tcx()) {
             ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
-            ty::AliasTermKind::ProjectionTy
-            | ty::AliasTermKind::WeakTy
-            | ty::AliasTermKind::OpaqueTy
-            | ty::AliasTermKind::UnevaluatedConst
-            | ty::AliasTermKind::ProjectionConst => {
-                // If we're printing verbosely, or don't want to invoke queries
-                // (`is_impl_trait_in_trait`), then fall back to printing the def path.
-                // This is likely what you want if you're debugging the compiler anyways.
+            ty::AliasTermKind::ProjectionTy => {
                 if !(cx.should_print_verbose() || with_reduced_queries())
                     && cx.tcx().is_impl_trait_in_trait(self.def_id)
                 {
-                    return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
+                    p!(pretty_print_rpitit(self.def_id, self.args))
                 } else {
                     p!(print_def_path(self.def_id, self.args));
                 }
             }
+            | ty::AliasTermKind::WeakTy
+            | ty::AliasTermKind::OpaqueTy
+            | ty::AliasTermKind::UnevaluatedConst
+            | ty::AliasTermKind::ProjectionConst => {
+                p!(print_def_path(self.def_id, self.args));
+            }
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6c62c04f42e..f1d03d0a659 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -50,7 +50,7 @@ impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
 
 impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let name = ty::tls::with(|tcx| tcx.hir().name(self.var_path.hir_id));
+        let name = ty::tls::with(|tcx| tcx.hir_name(self.var_path.hir_id));
         write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, name, self.closure_expr_id)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 7d9c23c05f9..06054e22e76 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -310,7 +310,7 @@ impl<'tcx> TypeckResults<'tcx> {
 
     pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
-            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
+            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir_id_to_string(id)))
         })
     }
 
@@ -554,7 +554,7 @@ fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
     ty::tls::with(|tcx| {
         bug!(
             "node {} cannot be placed in TypeckResults with hir_owner {:?}",
-            tcx.hir().node_to_string(hir_id),
+            tcx.hir_id_to_string(hir_id),
             hir_owner
         )
     });
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index f9fa750e750..2909dea98b7 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -485,7 +485,7 @@ fn construct_fn<'tcx>(
     };
 
     if let Some(custom_mir_attr) =
-        tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
+        tcx.hir_attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
     {
         return custom::build_custom_mir(
             tcx,
@@ -741,7 +741,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         coroutine: Option<Box<CoroutineInfo<'tcx>>>,
     ) -> Builder<'a, 'tcx> {
         let tcx = infcx.tcx;
-        let attrs = tcx.hir().attrs(hir_id);
+        let attrs = tcx.hir_attrs(hir_id);
         // Some functions always have overflow checks enabled,
         // however, they may not get codegen'd, depending on
         // the settings for the crate they are codegened in.
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 81561239491..27ff01b4803 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -942,14 +942,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         assert_eq!(orig_id.owner, self.hir_id.owner);
 
         let mut id = orig_id;
-        let hir = self.tcx.hir();
         loop {
             if id == self.hir_id {
                 // This is a moderately common case, mostly hit for previously unseen nodes.
                 break;
             }
 
-            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
+            if self.tcx.hir_attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
                 // This is a rare case. It's for a node path that doesn't reach the root due to an
                 // intervening lint level attribute. This result doesn't get cached.
                 return id;
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index d78c874c766..7f2e7d5ca83 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -753,6 +753,11 @@ impl UnsafeOpKind {
         span: Span,
         suggest_unsafe_block: bool,
     ) {
+        if tcx.hir_opt_delegation_sig_id(hir_id.owner.def_id).is_some() {
+            // The body of the delegation item is synthesized, so it makes no sense
+            // to emit this lint.
+            return;
+        }
         let parent_id = tcx.hir_get_parent_item(hir_id);
         let parent_owner = tcx.hir_owner_node(parent_id);
         let should_suggest = parent_owner.fn_sig().is_some_and(|sig| {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index fa5db32d913..a25697ba086 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -3,12 +3,12 @@
 // tidy-alphabetical-start
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 // The `builder` module used to be named `build`, but that was causing GitHub's
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index e46e8c9871a..b8af77245f2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1041,7 +1041,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
                         "Should have already errored about late bound consts: {def_id:?}"
                     );
                 };
-                let name = self.tcx.hir().name(hir_id);
+                let name = self.tcx.hir_name(hir_id);
                 let param = ty::ParamConst::new(index, name);
 
                 ExprKind::ConstParam { param, def_id }
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 3d55c1401b6..b3daed8a7e0 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -73,7 +73,6 @@ struct ThirBuildCx<'tcx> {
 impl<'tcx> ThirBuildCx<'tcx> {
     fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
         let typeck_results = tcx.typeck(def);
-        let hir = tcx.hir();
         let hir_id = tcx.local_def_id_to_hir_id(def);
 
         let body_type = match tcx.hir_body_owner_kind(def) {
@@ -111,8 +110,8 @@ impl<'tcx> ThirBuildCx<'tcx> {
             typeck_results,
             rvalue_scopes: &typeck_results.rvalue_scopes,
             body_owner: def.to_def_id(),
-            apply_adjustments: hir
-                .attrs(hir_id)
+            apply_adjustments: tcx
+                .hir_attrs(hir_id)
                 .iter()
                 .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
         }
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 dadd1e85461..cbd29ba837e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1043,7 +1043,7 @@ fn find_fallback_pattern_typo<'tcx>(
         for item in cx.tcx.hir_crate_items(()).free_items() {
             if let DefKind::Use = cx.tcx.def_kind(item.owner_id) {
                 // Look for consts being re-exported.
-                let item = cx.tcx.hir().expect_item(item.owner_id.def_id);
+                let item = cx.tcx.hir_expect_item(item.owner_id.def_id);
                 let use_name = item.ident.name;
                 let hir::ItemKind::Use(path, _) = item.kind else {
                     continue;
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index a8a56baa1ff..82c57ef5678 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,4 +1,5 @@
 // tidy-alphabetical-start
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(assert_matches)]
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
@@ -7,7 +8,6 @@
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_middle::ty;
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index bc335cee147..bacff287859 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -32,9 +32,12 @@ pub(super) use self::AddCallGuards::*;
 
 impl<'tcx> crate::MirPass<'tcx> for AddCallGuards {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        let mut pred_count: IndexVec<_, _> =
-            body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect();
-        pred_count[START_BLOCK] += 1;
+        let mut pred_count = IndexVec::from_elem(0u8, &body.basic_blocks);
+        for (_, data) in body.basic_blocks.iter_enumerated() {
+            for succ in data.terminator().successors() {
+                pred_count[succ] = pred_count[succ].saturating_add(1);
+            }
+        }
 
         // We need a place to store the new blocks generated
         let mut new_blocks = Vec::new();
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 8aa14d15644..205d388f4fb 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,4 +1,5 @@
 // tidy-alphabetical-start
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -12,7 +13,6 @@
 #![feature(never_type)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use hir::ConstContext;
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 714b64b3a23..5dbae50c499 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,10 +1,10 @@
 // tidy-alphabetical-start
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(array_windows)]
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(let_chains)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_hir::lang_items::LangItem;
diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
index 0c855508434..ebe0b258c1b 100644
--- a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
@@ -12,21 +12,15 @@ fn adjust_activity_to_abi<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec
     if !matches!(fn_ty.kind(), ty::FnDef(..)) {
         bug!("expected fn def for autodiff, got {:?}", fn_ty);
     }
-    let fnc_binder: ty::Binder<'_, ty::FnSig<'_>> = fn_ty.fn_sig(tcx);
 
-    // If rustc compiles the unmodified primal, we know that this copy of the function
-    // also has correct lifetimes. We know that Enzyme won't free the shadow too early
-    // (or actually at all), so let's strip lifetimes when computing the layout.
-    let x = tcx.instantiate_bound_regions_with_erased(fnc_binder);
+    // We don't actually pass the types back into the type system.
+    // All we do is decide how to handle the arguments.
+    let sig = fn_ty.fn_sig(tcx).skip_binder();
+
     let mut new_activities = vec![];
     let mut new_positions = vec![];
-    for (i, ty) in x.inputs().iter().enumerate() {
+    for (i, ty) in sig.inputs().iter().enumerate() {
         if let Some(inner_ty) = ty.builtin_deref(true) {
-            if ty.is_fn_ptr() {
-                // FIXME(ZuseZ4): add a nicer error, or just figure out how to support them,
-                // since Enzyme itself can handle them.
-                tcx.dcx().err("function pointers are currently not supported in autodiff");
-            }
             if inner_ty.is_slice() {
                 // We know that the length will be passed as extra arg.
                 if !da.is_empty() {
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index d67ae2550d9..f6963a79067 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -6,7 +6,6 @@
 
 // tidy-alphabetical-start
 #![allow(rustc::usage_of_type_ir_inherent)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod canonicalizer;
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 b0bbec48947..e48ee71c858 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
@@ -271,12 +271,39 @@ where
     /// and will need to clearly document it in the rustc-dev-guide before
     /// stabilization.
     pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
-        match (self.current_goal_kind, source) {
-            (_, GoalSource::NormalizeGoal(step_kind)) => step_kind,
-            (CurrentGoalKind::CoinductiveTrait, GoalSource::ImplWhereBound) => {
-                PathKind::Coinductive
+        match source {
+            // We treat these goals as unknown for now. It is likely that most miscellaneous
+            // nested goals will be converted to an inductive variant in the future.
+            //
+            // Having unknown cycles is always the safer option, as changing that to either
+            // succeed or hard error is backwards compatible. If we incorrectly treat a cycle
+            // as inductive even though it should not be, it may be unsound during coherence and
+            // fixing it may cause inference breakage or introduce ambiguity.
+            GoalSource::Misc => PathKind::Unknown,
+            GoalSource::NormalizeGoal(path_kind) => path_kind,
+            GoalSource::ImplWhereBound => {
+                // We currently only consider a cycle coinductive if it steps
+                // into a where-clause of a coinductive trait.
+                //
+                // We probably want to make all traits coinductive in the future,
+                // so we treat cycles involving their where-clauses as ambiguous.
+                if let CurrentGoalKind::CoinductiveTrait = self.current_goal_kind {
+                    PathKind::Coinductive
+                } else {
+                    PathKind::Unknown
+                }
             }
-            _ => PathKind::Inductive,
+            // Relating types is always unproductive. If we were to map proof trees to
+            // corecursive functions as explained in #136824, relating types never
+            // introduces a constructor which could cause the recursion to be guarded.
+            GoalSource::TypeRelating => PathKind::Inductive,
+            // Instantiating a higher ranked goal can never cause the recursion to be
+            // guarded and is therefore unproductive.
+            GoalSource::InstantiateHigherRanked => PathKind::Inductive,
+            // These goal sources are likely unproductive and can be changed to
+            // `PathKind::Inductive`. Keeping them as unknown until we're confident
+            // about this and have an example where it is necessary.
+            GoalSource::AliasBoundConstCondition | GoalSource::AliasWellFormed => PathKind::Unknown,
         }
     }
 
@@ -606,7 +633,7 @@ where
 
             let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
                 GoalEvaluationKind::Nested,
-                GoalSource::Misc,
+                GoalSource::TypeRelating,
                 unconstrained_goal,
             )?;
             // Add the nested goals from normalization to our own nested goals.
@@ -683,7 +710,7 @@ where
     pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<I, ty::NormalizesTo<I>>) {
         goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(
             self,
-            GoalSource::Misc,
+            GoalSource::TypeRelating,
             goal.param_env,
         ));
         self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
@@ -939,7 +966,15 @@ where
         rhs: T,
     ) -> Result<(), NoSolution> {
         let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
-        self.add_goals(GoalSource::Misc, goals);
+        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:?}"),
+                }
+            }
+        }
+        self.add_goals(GoalSource::TypeRelating, goals);
         Ok(())
     }
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index 1607fbb1b6a..6a8e0790f7c 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -421,7 +421,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         self.add_goal(
             delegate,
             max_input_universe,
-            GoalSource::Misc,
+            GoalSource::TypeRelating,
             goal.with(delegate.cx(), goal.predicate),
         );
     }
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 1fa35b60304..199f0c7512e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -313,7 +313,9 @@ where
                     ty::AliasRelationDirection::Equate,
                 ),
             );
-            self.add_goal(GoalSource::Misc, alias_relate_goal);
+            // We normalize the self type to be able to relate it with
+            // types from candidates.
+            self.add_goal(GoalSource::TypeRelating, alias_relate_goal);
             self.try_evaluate_added_goals()?;
             Ok(self.resolve_vars_if_possible(normalized_term))
         } else {
diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
index d9452880071..944d5f0e042 100644
--- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
@@ -24,7 +24,8 @@ where
                 ty::AliasRelationDirection::Equate,
             ),
         );
-        self.add_goal(GoalSource::Misc, goal);
+        // A projection goal holds if the alias is equal to the expected term.
+        self.add_goal(GoalSource::TypeRelating, goal);
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
index 67eb442d2cc..eba496fa226 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -1,9 +1,9 @@
 use std::convert::Infallible;
 use std::marker::PhantomData;
 
-use rustc_type_ir::Interner;
 use rustc_type_ir::search_graph::{self, PathKind};
-use rustc_type_ir::solve::{CanonicalInput, Certainty, QueryResult};
+use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult};
+use rustc_type_ir::{Interner, TypingMode};
 
 use super::inspect::ProofTreeBuilder;
 use super::{FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints};
@@ -47,7 +47,24 @@ where
     ) -> QueryResult<I> {
         match kind {
             PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes),
-            PathKind::Inductive => response_no_constraints(cx, input, Certainty::overflow(false)),
+            PathKind::Unknown => response_no_constraints(cx, input, Certainty::overflow(false)),
+            // Even though we know these cycles to be unproductive, we still return
+            // overflow during coherence. This is both as we are not 100% confident in
+            // the implementation yet and any incorrect errors would be unsound there.
+            // The affected cases are also fairly artificial and not necessarily desirable
+            // so keeping this as ambiguity is fine for now.
+            //
+            // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an
+            // example where this would matter. We likely should change these cycles to `NoSolution`
+            // even in coherence once this is a bit more settled.
+            PathKind::Inductive => match input.typing_mode {
+                TypingMode::Coherence => {
+                    response_no_constraints(cx, input, Certainty::overflow(false))
+                }
+                TypingMode::Analysis { .. }
+                | TypingMode::PostBorrowckAnalysis { .. }
+                | TypingMode::PostAnalysis => Err(NoSolution),
+            },
         }
     }
 
@@ -57,12 +74,7 @@ where
         input: CanonicalInput<I>,
         result: QueryResult<I>,
     ) -> bool {
-        match kind {
-            PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes) == result,
-            PathKind::Inductive => {
-                response_no_constraints(cx, input, Certainty::overflow(false)) == result
-            }
-        }
+        Self::initial_provisional_result(cx, kind, input) == result
     }
 
     fn on_stack_overflow(
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 1a104ff5e33..79939aab7fc 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -4,6 +4,7 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -12,7 +13,6 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(string_from_utf8_lossy_owned)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::path::{Path, PathBuf};
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index b37dd64fbed..9b2d562a69e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1364,7 +1364,6 @@ impl<'a> Parser<'a> {
                     self.bump();
                     return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None)));
                 }
-                _ => {}
             };
         } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| {
             this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))
@@ -3064,7 +3063,7 @@ impl<'a> Parser<'a> {
             }
 
             self.restore_snapshot(pre_pat_snapshot);
-            match self.parse_stmt_without_recovery(true, ForceCollect::No) {
+            match self.parse_stmt_without_recovery(true, ForceCollect::No, false) {
                 // Consume statements for as long as possible.
                 Ok(Some(stmt)) => {
                     stmts.push(stmt);
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 9e6cdfe59bb..2388463ecfc 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -21,10 +21,10 @@ use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
     AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, Parser, PathStyle,
-    Trailing, UsePreAttrPos,
+    Recovered, Trailing, UsePreAttrPos,
 };
 use crate::errors::{self, MacroExpandsToAdtField};
-use crate::{exp, fluent_generated as fluent, maybe_whole};
+use crate::{exp, fluent_generated as fluent};
 
 impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
@@ -142,10 +142,13 @@ impl<'a> Parser<'a> {
         fn_parse_mode: FnParseMode,
         force_collect: ForceCollect,
     ) -> PResult<'a, Option<Item>> {
-        maybe_whole!(self, NtItem, |item| {
+        if let Some(item) =
+            self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes))
+        {
+            let mut item = item.expect("an actual item");
             attrs.prepend_to_nt_inner(&mut item.attrs);
-            Some(item.into_inner())
-        });
+            return Ok(Some(item.into_inner()));
+        }
 
         self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
             let lo = this.token.span;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4ec8d9e5e49..323c0c1d6d0 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1076,10 +1076,12 @@ impl<'a> Parser<'a> {
         let initial_semicolon = self.token.span;
 
         while self.eat(exp!(Semi)) {
-            let _ = self.parse_stmt_without_recovery(false, ForceCollect::No).unwrap_or_else(|e| {
-                e.cancel();
-                None
-            });
+            let _ = self
+                .parse_stmt_without_recovery(false, ForceCollect::No, false)
+                .unwrap_or_else(|e| {
+                    e.cancel();
+                    None
+                });
         }
 
         expect_err
@@ -1746,6 +1748,8 @@ pub enum ParseNtResult {
     Tt(TokenTree),
     Ident(Ident, IdentIsRaw),
     Lifetime(Ident, IdentIsRaw),
+    Item(P<ast::Item>),
+    Stmt(P<ast::Stmt>),
     Pat(P<ast::Pat>, NtPatKind),
     Ty(P<ast::Ty>),
     Meta(P<ast::AttrItem>),
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index d537bc17ce3..1123755ce00 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -48,12 +48,11 @@ impl<'a> Parser<'a> {
         /// Old variant of `may_be_ident`. Being phased out.
         fn nt_may_be_ident(nt: &Nonterminal) -> bool {
             match nt {
-                NtStmt(_)
-                | NtExpr(_)
+                NtExpr(_)
                 | NtLiteral(_) // `true`, `false`
                 => true,
 
-                NtItem(_) | NtBlock(_) => false,
+                NtBlock(_) => false,
             }
         }
 
@@ -96,8 +95,7 @@ impl<'a> Parser<'a> {
                 token::OpenDelim(Delimiter::Brace) => true,
                 token::NtLifetime(..) => true,
                 token::Interpolated(nt) => match &**nt {
-                    NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
-                    NtItem(_) => false,
+                    NtBlock(_) | NtExpr(_) | NtLiteral(_) => true,
                 },
                 token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
                     MetaVarKind::Block
@@ -147,7 +145,7 @@ impl<'a> Parser<'a> {
             // Note that TT is treated differently to all the others.
             NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
-                Some(item) => NtItem(item),
+                Some(item) => return Ok(ParseNtResult::Item(item)),
                 None => {
                     return Err(self
                         .dcx()
@@ -160,7 +158,7 @@ impl<'a> Parser<'a> {
                 NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
-                Some(s) => NtStmt(P(s)),
+                Some(stmt) => return Ok(ParseNtResult::Stmt(P(stmt))),
                 None => {
                     return Err(self
                         .dcx()
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 3a9dc5ce798..0896bd88b4c 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -5,7 +5,7 @@ use std::ops::Bound;
 use ast::Label;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, TokenKind};
+use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
 use rustc_ast::util::classify::{self, TrailingBrace};
 use rustc_ast::{
     AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local,
@@ -33,8 +33,8 @@ impl<'a> Parser<'a> {
     /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
     /// whether or not we have attributes.
     // Public for rustfmt usage.
-    pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
-        Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
+    pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
+        Ok(self.parse_stmt_without_recovery(false, force_collect, false).unwrap_or_else(|e| {
             e.emit();
             self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
             None
@@ -42,23 +42,27 @@ impl<'a> Parser<'a> {
     }
 
     /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
-    /// whether or not we have attributes.
-    // Public for `cfg_eval` macro expansion.
+    /// whether or not we have attributes. If `force_full_expr` is true, parses the stmt without
+    /// using `Restriction::STMT_EXPR`. Public for `cfg_eval` macro expansion.
     pub fn parse_stmt_without_recovery(
         &mut self,
         capture_semi: bool,
         force_collect: ForceCollect,
+        force_full_expr: bool,
     ) -> PResult<'a, Option<Stmt>> {
         let pre_attr_pos = self.collect_pos();
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
 
-        maybe_whole!(self, NtStmt, |stmt| {
+        if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| {
+            this.parse_stmt_without_recovery(false, ForceCollect::Yes, false)
+        }) {
+            let mut stmt = stmt.expect("an actual statement");
             stmt.visit_attrs(|stmt_attrs| {
                 attrs.prepend_to_nt_inner(stmt_attrs);
             });
-            Some(stmt.into_inner())
-        });
+            return Ok(Some(stmt));
+        }
 
         if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
             self.bump();
@@ -147,12 +151,14 @@ impl<'a> Parser<'a> {
         } else if self.token != token::CloseDelim(Delimiter::Brace) {
             // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case
             // above.
+            let restrictions =
+                if force_full_expr { Restrictions::empty() } else { Restrictions::STMT_EXPR };
             let e = self.collect_tokens(
                 Some(pre_attr_pos),
                 AttrWrapper::empty(),
                 force_collect,
                 |this, _empty_attrs| {
-                    let (expr, _) = this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?;
+                    let (expr, _) = this.parse_expr_res(restrictions, attrs)?;
                     Ok((expr, Trailing::No, UsePreAttrPos::Yes))
                 },
             )?;
@@ -229,11 +235,15 @@ impl<'a> Parser<'a> {
         let mac = P(MacCall { path, args });
 
         let kind = if (style == MacStmtStyle::Braces
-            && self.token != token::Dot
-            && self.token != token::Question)
-            || self.token == token::Semi
-            || self.token == token::Eof
-        {
+            && !matches!(self.token.kind, token::Dot | token::Question))
+            || matches!(
+                self.token.kind,
+                token::Semi
+                    | token::Eof
+                    | token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
+                        MetaVarKind::Stmt
+                    )))
+            ) {
             StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
         } else {
             // Since none of the above applied, this is an expression statement macro.
@@ -501,7 +511,7 @@ impl<'a> Parser<'a> {
         //      bar;
         //
         // which is valid in other languages, but not Rust.
-        match self.parse_stmt_without_recovery(false, ForceCollect::No) {
+        match self.parse_stmt_without_recovery(false, ForceCollect::No, false) {
             // If the next token is an open brace, e.g., we have:
             //
             //     if expr other_expr {
@@ -810,10 +820,24 @@ impl<'a> Parser<'a> {
         &mut self,
         recover: AttemptLocalParseRecovery,
     ) -> PResult<'a, Option<Stmt>> {
-        // Skip looking for a trailing semicolon when we have an interpolated statement.
-        maybe_whole!(self, NtStmt, |stmt| Some(stmt.into_inner()));
+        // Skip looking for a trailing semicolon when we have a metavar seq.
+        if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| {
+            // Why pass `true` for `force_full_expr`? Statement expressions are less expressive
+            // than "full" expressions, due to the `STMT_EXPR` restriction, and sometimes need
+            // parentheses. E.g. the "full" expression `match paren_around_match {} | true` when
+            // used in statement context must be written `(match paren_around_match {} | true)`.
+            // However, if the expression we are parsing in this statement context was pasted by a
+            // declarative macro, it may have come from a "full" expression context, and lack
+            // these parentheses. So we lift the `STMT_EXPR` restriction to ensure the statement
+            // will reparse successfully.
+            this.parse_stmt_without_recovery(false, ForceCollect::No, true)
+        }) {
+            let stmt = stmt.expect("an actual statement");
+            return Ok(Some(stmt));
+        }
 
-        let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else {
+        let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No, false)?
+        else {
             return Ok(None);
         };
 
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index e05cc6d29d8..5b8a2fe52d3 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -13,7 +13,6 @@
     html_playground_url = "https://play.rust-lang.org/",
     test(attr(deny(warnings)))
 )]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub use Alignment::*;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c6ae2c0fb9b..ece5a53aaa9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -52,7 +52,7 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>)
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
             let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-            let containing_item = tcx.hir().expect_item(parent_def_id);
+            let containing_item = tcx.hir_expect_item(parent_def_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
                 _ => bug!("parent of an ImplItem must be an Impl"),
@@ -114,7 +114,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut doc_aliases = FxHashMap::default();
         let mut specified_inline = None;
         let mut seen = FxHashMap::default();
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
         for attr in attrs {
             match attr {
                 Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
@@ -899,7 +899,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         if let Some(location) = match target {
             Target::AssocTy => {
                 let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
-                let containing_item = self.tcx.hir().expect_item(parent_def_id);
+                let containing_item = self.tcx.hir_expect_item(parent_def_id);
                 if Target::from_item(containing_item) == Target::Impl {
                     Some("type alias in implementation block")
                 } else {
@@ -908,7 +908,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             }
             Target::AssocConst => {
                 let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
-                let containing_item = self.tcx.hir().expect_item(parent_def_id);
+                let containing_item = self.tcx.hir_expect_item(parent_def_id);
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
                 match containing_item.kind {
@@ -952,7 +952,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return;
         }
-        let item_name = self.tcx.hir().name(hir_id);
+        let item_name = self.tcx.hir_name(hir_id);
         if item_name == doc_alias {
             tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str });
             return;
@@ -1481,7 +1481,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         // `#[must_use]` can be applied to a trait method definition with a default body
         if let Target::Method(MethodKind::Trait { body: true }) = target
             && let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id
-            && let containing_item = self.tcx.hir().expect_item(parent_def_id)
+            && let containing_item = self.tcx.hir_expect_item(parent_def_id)
             && let hir::ItemKind::Trait(..) = containing_item.kind
         {
             return;
@@ -2572,7 +2572,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         match (target, force_inline_attr) {
             (Target::Closure, None) => {
                 let is_coro = matches!(
-                    self.tcx.hir().expect_expr(hir_id).kind,
+                    self.tcx.hir_expect_expr(hir_id).kind,
                     hir::ExprKind::Closure(hir::Closure {
                         kind: hir::ClosureKind::Coroutine(..)
                             | hir::ClosureKind::CoroutineClosure(..),
@@ -2644,8 +2644,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr];
         let spans = self
             .tcx
-            .hir()
-            .attrs(where_predicate.hir_id)
+            .hir_attrs(where_predicate.hir_id)
             .iter()
             .filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym)))
             .map(|attr| attr.span())
@@ -2814,7 +2813,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 }
 
 fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
-    let attrs = tcx.hir().attrs(item.hir_id());
+    let attrs = tcx.hir_attrs(item.hir_id());
 
     for attr in attrs {
         if attr.has_name(sym::inline) {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 7a14a7a5db2..7029c60c343 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -361,7 +361,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
                 && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
                 && let TyKind::Path(hir::QPath::Resolved(_, path)) =
-                    self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
+                    self.tcx.hir_expect_item(local_impl_of).expect_impl().self_ty.kind
                 && let Res::Def(def_kind, did) = path.res
             {
                 match def_kind {
@@ -424,7 +424,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     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
+                                self.tcx.hir_expect_item(local_def_id).kind
                         {
                             // skip items
                             // mark dependent traits live
@@ -448,7 +448,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     for impl_id in self.tcx.all_impls(trait_id) {
                         if let Some(local_impl_id) = impl_id.as_local()
                             && let ItemKind::Impl(impl_ref) =
-                                self.tcx.hir().expect_item(local_impl_id).kind
+                                self.tcx.hir_expect_item(local_impl_id).kind
                         {
                             if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
                                 && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 323b414cca0..e13d94c1031 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -19,7 +19,7 @@ use rustc_span::{Symbol, sym};
 use crate::errors::DuplicateDiagnosticItemInCrate;
 
 fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
-    let attrs = tcx.hir().attrs(owner.into());
+    let attrs = tcx.hir_attrs(owner.into());
     if let Some(name) = extract(attrs) {
         // insert into our table
         collect_item(tcx, diagnostic_items, name, owner.to_def_id());
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 25e679a8460..d2729876ebb 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -31,7 +31,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(tcx.hir().attrs(CRATE_HIR_ID), sym::no_main) {
+    if attr::contains_name(tcx.hir_attrs(CRATE_HIR_ID), sym::no_main) {
         return None;
     }
 
@@ -45,7 +45,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
 }
 
 fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let attrs = ctxt.tcx.hir_attrs(id.hir_id());
     attr::find_by_name(attrs, sym).map(|attr| attr.span())
 }
 
@@ -61,7 +61,7 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let attrs = ctxt.tcx.hir_attrs(id.hir_id());
     let entry_point_type = rustc_ast::entry::entry_point_type(
         attrs,
         at_root,
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 509c2f54775..84b92d49f24 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -60,19 +60,18 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
             .expect("owning item has no entry");
 
         if max != self.hir_ids_seen.len() - 1 {
-            let hir = self.tcx.hir();
             let pretty_owner = self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose();
 
             let missing_items: Vec<_> = (0..=max as u32)
                 .map(|i| ItemLocalId::from_u32(i))
                 .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
-                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .map(|local_id| self.tcx.hir_id_to_string(HirId { owner, local_id }))
                 .collect();
 
             let seen_items: Vec<_> = self
                 .hir_ids_seen
                 .iter()
-                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .map(|local_id| self.tcx.hir_id_to_string(HirId { owner, local_id }))
                 .collect();
 
             self.error(|| {
@@ -137,7 +136,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
             self.error(|| {
                 format!(
                     "HirIdValidator: The recorded owner of {} is {} instead of {}",
-                    self.tcx.hir().node_to_string(hir_id),
+                    self.tcx.hir_id_to_string(hir_id),
                     self.tcx.hir_def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
                     self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose()
                 )
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 1aa077ad2bb..6f6115af96c 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -6,13 +6,13 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 822804893fe..ed70d9ee91f 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -157,7 +157,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
     if let Some(upvars) = tcx.upvars_mentioned(def_id) {
         for &var_hir_id in upvars.keys() {
-            let var_name = tcx.hir().name(var_hir_id);
+            let var_name = tcx.hir_name(var_hir_id);
             maps.add_variable(Upvar(var_hir_id, var_name));
         }
     }
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 8e59c0b3251..b06f16cc7bd 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -222,7 +222,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
 
                 if let Some(break_expr) = opt_expr {
                     let (head, loop_label, loop_kind) = if let Some(loop_id) = loop_id {
-                        match self.tcx.hir().expect_expr(loop_id).kind {
+                        match self.tcx.hir_expect_expr(loop_id).kind {
                             hir::ExprKind::Loop(_, label, source, sp) => {
                                 (Some(sp), label, Some(source))
                             }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index fd465717bf7..599a08bac20 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -291,7 +291,7 @@ impl<'tcx> ReachableContext<'tcx> {
             _ => {
                 bug!(
                     "found unexpected node kind in worklist: {} ({:?})",
-                    self.tcx.hir().node_to_string(self.tcx.local_def_id_to_hir_id(search_item)),
+                    self.tcx.hir_id_to_string(self.tcx.local_def_id_to_hir_id(search_item)),
                     node,
                 );
             }
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 0fcf6a80ec4..aea4386295f 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -118,7 +118,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
     ) where
         F: FnOnce(&mut Self),
     {
-        let attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
+        let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
         debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
 
         let depr = attr::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
@@ -795,7 +795,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
             }) => {
                 let features = self.tcx.features();
                 if features.staged_api() {
-                    let attrs = self.tcx.hir().attrs(item.hir_id());
+                    let attrs = self.tcx.hir_attrs(item.hir_id());
                     let stab = attr::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
 
                     // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
@@ -1034,7 +1034,7 @@ fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     }
 
     // If this is a path that isn't a use, we don't need to do anything special
-    if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) {
+    if !matches!(tcx.hir_expect_item(def_id).kind, ItemKind::Use(..)) {
         return false;
     }
 
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index a3400ebb799..eeea724a29b 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,7 +6,6 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 #![cfg_attr(feature = "rustc", feature(let_chains))]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod constructor;
diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs
index 365bc2d863f..8980b644f59 100644
--- a/compiler/rustc_pattern_analysis/tests/common/mod.rs
+++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs
@@ -5,7 +5,7 @@ use rustc_pattern_analysis::usefulness::{PlaceValidity, UsefulnessReport};
 use rustc_pattern_analysis::{MatchArm, PatCx, PrivateUninhabitedField};
 
 /// Sets up `tracing` for easier debugging. Tries to look like the `rustc` setup.
-pub fn init_tracing() {
+fn init_tracing() {
     use tracing_subscriber::Layer;
     use tracing_subscriber::layer::SubscriberExt;
     use tracing_subscriber::util::SubscriberInitExt;
@@ -24,7 +24,7 @@ pub fn init_tracing() {
 /// A simple set of types.
 #[allow(dead_code)]
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum Ty {
+pub(super) enum Ty {
     /// Booleans
     Bool,
     /// 8-bit unsigned integers
@@ -41,7 +41,7 @@ pub enum Ty {
 
 /// The important logic.
 impl Ty {
-    pub fn sub_tys(&self, ctor: &Constructor<Cx>) -> Vec<Self> {
+    pub(super) fn sub_tys(&self, ctor: &Constructor<Cx>) -> Vec<Self> {
         use Constructor::*;
         match (ctor, *self) {
             (Struct, Ty::Tuple(tys)) => tys.iter().copied().collect(),
@@ -63,7 +63,7 @@ impl Ty {
         }
     }
 
-    pub fn ctor_set(&self) -> ConstructorSet<Cx> {
+    fn ctor_set(&self) -> ConstructorSet<Cx> {
         match *self {
             Ty::Bool => ConstructorSet::Bool,
             Ty::U8 => ConstructorSet::Integers {
@@ -104,7 +104,7 @@ impl Ty {
         }
     }
 
-    pub fn write_variant_name(
+    fn write_variant_name(
         &self,
         f: &mut std::fmt::Formatter<'_>,
         ctor: &Constructor<Cx>,
@@ -120,7 +120,7 @@ impl Ty {
 }
 
 /// Compute usefulness in our simple context (and set up tracing for easier debugging).
-pub fn compute_match_usefulness<'p>(
+pub(super) fn compute_match_usefulness<'p>(
     arms: &[MatchArm<'p, Cx>],
     ty: Ty,
     scrut_validity: PlaceValidity,
@@ -137,7 +137,7 @@ pub fn compute_match_usefulness<'p>(
 }
 
 #[derive(Debug)]
-pub struct Cx;
+pub(super) struct Cx;
 
 /// The context for pattern analysis. Forwards anything interesting to `Ty` methods.
 impl PatCx for Cx {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index ff203b2938e..cf32f237b86 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,12 +1,12 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(associated_type_defaults)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod errors;
@@ -493,7 +493,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
     ) {
         // Non-opaque macros cannot make other items more accessible than they already are.
         let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
 
         if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
             .unwrap_or(Transparency::fallback(md.macro_rules))
@@ -573,7 +573,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             // have normal hygiene, so we can treat them like other items without type
             // privacy and mark them reachable.
             DefKind::Macro(_) => {
-                let item = self.tcx.hir().expect_item(def_id);
+                let item = self.tcx.hir_expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind {
                     if vis.is_accessible_from(module, self.tcx) {
                         self.update(def_id, macro_ev, Level::Reachable);
@@ -597,7 +597,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
 
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
-                let item = self.tcx.hir().expect_item(def_id);
+                let item = self.tcx.hir_expect_item(def_id);
                 if let hir::ItemKind::Struct(ref struct_def, _)
                 | hir::ItemKind::Union(ref struct_def, _) = item.kind
                 {
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 73c205fdb17..a83c388c747 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -3,12 +3,12 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(unused_parens)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_data_structures::stable_hasher::HashStable;
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 6ece01c211b..3109d53cd2c 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1,5 +1,4 @@
 use std::assert_matches::assert_matches;
-use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -9,7 +8,7 @@ use std::sync::atomic::{AtomicU32, Ordering};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
-use rustc_data_structures::sharded::{self, Sharded};
+use rustc_data_structures::sharded::{self, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_data_structures::unord::UnordMap;
@@ -619,7 +618,7 @@ impl<D: Deps> DepGraphData<D> {
         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.lock_shard_by_value(dep_node).get(dep_node).copied()
+            self.current.new_node_to_index.get(dep_node)
         }
     }
 
@@ -1048,7 +1047,7 @@ rustc_index::newtype_index! {
 /// first, and `data` second.
 pub(super) struct CurrentDepGraph<D: Deps> {
     encoder: GraphEncoder<D>,
-    new_node_to_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
+    new_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
     prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
 
     /// This is used to verify that fingerprints do not change between the creation of a node
@@ -1117,12 +1116,9 @@ impl<D: Deps> CurrentDepGraph<D> {
                 profiler,
                 previous,
             ),
-            new_node_to_index: Sharded::new(|| {
-                FxHashMap::with_capacity_and_hasher(
-                    new_node_count_estimate / sharded::shards(),
-                    Default::default(),
-                )
-            }),
+            new_node_to_index: ShardedHashMap::with_capacity(
+                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)]
@@ -1152,14 +1148,9 @@ impl<D: Deps> CurrentDepGraph<D> {
         edges: EdgesVec,
         current_fingerprint: Fingerprint,
     ) -> DepNodeIndex {
-        let dep_node_index = match self.new_node_to_index.lock_shard_by_value(&key).entry(key) {
-            Entry::Occupied(entry) => *entry.get(),
-            Entry::Vacant(entry) => {
-                let dep_node_index = self.encoder.send(key, current_fingerprint, edges);
-                entry.insert(dep_node_index);
-                dep_node_index
-            }
-        };
+        let dep_node_index = self
+            .new_node_to_index
+            .get_or_insert_with(key, || self.encoder.send(key, current_fingerprint, edges));
 
         #[cfg(debug_assertions)]
         self.record_edge(dep_node_index, key, current_fingerprint);
@@ -1257,7 +1248,7 @@ impl<D: Deps> CurrentDepGraph<D> {
     ) {
         let node = &prev_graph.index_to_node(prev_index);
         debug_assert!(
-            !self.new_node_to_index.lock_shard_by_value(node).contains_key(node),
+            !self.new_node_to_index.get(node).is_some(),
             "node from previous graph present in new node collection"
         );
     }
@@ -1382,7 +1373,7 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
     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) {
+            if let Some((node, _)) = shard.iter().find(|(_, index)| *index == dep_node_index) {
                 dep_node = Some(*node);
                 break;
             }
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index ee984095ad8..2aedd365adc 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -3,10 +3,8 @@
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
-#![feature(hash_raw_entry)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod cache;
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 3b47e7eba0f..30b5d7e5954 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -2,8 +2,7 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::sync::OnceLock;
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sharded::{self, Sharded};
+use rustc_data_structures::sharded::ShardedHashMap;
 pub use rustc_data_structures::vec_cache::VecCache;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_index::Idx;
@@ -36,7 +35,7 @@ pub trait QueryCache: Sized {
 /// In-memory cache for queries whose keys aren't suitable for any of the
 /// more specialized kinds of cache. Backed by a sharded hashmap.
 pub struct DefaultCache<K, V> {
-    cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
+    cache: ShardedHashMap<K, (V, DepNodeIndex)>,
 }
 
 impl<K, V> Default for DefaultCache<K, V> {
@@ -55,19 +54,14 @@ where
 
     #[inline(always)]
     fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
-        let key_hash = sharded::make_hash(key);
-        let lock = self.cache.lock_shard_by_hash(key_hash);
-        let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
-
-        if let Some((_, value)) = result { Some(*value) } else { None }
+        self.cache.get(key)
     }
 
     #[inline]
     fn complete(&self, key: K, value: V, index: DepNodeIndex) {
-        let mut lock = self.cache.lock_shard_by_value(&key);
         // We may be overwriting another value. This is all right, since the dep-graph
         // will check that the fingerprint matches.
-        lock.insert(key, (value, index));
+        self.cache.insert(key, (value, index));
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 9f062b3935f..817aa5b4385 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -153,9 +153,13 @@ resolve_extern_crate_self_requires_renaming =
     `extern crate self;` requires renaming
     .suggestion = rename the `self` crate to be able to import it
 
+resolve_forward_declared_generic_in_const_param_ty =
+    const parameter types cannot reference parameters before they are declared
+    .label = const parameter type cannot reference `{$param}` before it is declared
+
 resolve_forward_declared_generic_param =
-    generic parameters with a default cannot use forward declared identifiers
-    .label = defaulted generic parameters cannot be forward declared
+    generic parameter defaults cannot reference parameters before they are declared
+    .label = cannot reference `{$param}` before it is declared
 
 resolve_found_an_item_configured_out =
     found an item that was configured out
@@ -377,9 +381,11 @@ resolve_self_imports_only_allowed_within_multipart_suggestion =
 resolve_self_imports_only_allowed_within_suggestion =
     consider importing the module directly
 
+resolve_self_in_const_generic_ty =
+    cannot use `Self` in const parameter type
+
 resolve_self_in_generic_param_default =
     generic parameters cannot use `Self` in their defaults
-    .label = `Self` in generic parameter default
 
 resolve_similarly_named_defined_here =
     similarly named {$candidate_descr} `{$candidate}` defined here
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 88d1126de1a..41f4254eede 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -42,10 +42,10 @@ use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::{
     AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
-    HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module, ModuleKind,
-    ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError,
-    ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, VisResolutionError,
-    errors as errs, path_names_to_string,
+    ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
+    ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
+    PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
+    VisResolutionError, errors as errs, path_names_to_string,
 };
 
 type Res = def::Res<ast::NodeId>;
@@ -887,9 +887,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 participle,
                 name,
             }),
-            ResolutionError::ForwardDeclaredGenericParam => {
-                self.dcx().create_err(errs::ForwardDeclaredGenericParam { span })
-            }
+            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
+                ForwardGenericParamBanReason::Default => {
+                    self.dcx().create_err(errs::ForwardDeclaredGenericParam { param, span })
+                }
+                ForwardGenericParamBanReason::ConstParamTy => self
+                    .dcx()
+                    .create_err(errs::ForwardDeclaredGenericInConstParamTy { param, span }),
+            },
             ResolutionError::ParamInTyOfConstParam { name } => {
                 self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
             }
@@ -908,9 +913,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
                 .dcx()
                 .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
-            ResolutionError::SelfInGenericParamDefault => {
-                self.dcx().create_err(errs::SelfInGenericParamDefault { span })
-            }
+            ResolutionError::ForwardDeclaredSelf(reason) => match reason {
+                ForwardGenericParamBanReason::Default => {
+                    self.dcx().create_err(errs::SelfInGenericParamDefault { span })
+                }
+                ForwardGenericParamBanReason::ConstParamTy => {
+                    self.dcx().create_err(errs::SelfInConstGenericTy { span })
+                }
+            },
             ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
                 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
                     match suggestion {
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index b5d3e5ea776..2ae6892bc93 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -338,6 +338,16 @@ pub(crate) struct ForwardDeclaredGenericParam {
     #[primary_span]
     #[label]
     pub(crate) span: Span,
+    pub(crate) param: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_forward_declared_generic_in_const_param_ty)]
+pub(crate) struct ForwardDeclaredGenericInConstParamTy {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) param: Symbol,
 }
 
 #[derive(Diagnostic)]
@@ -353,7 +363,13 @@ pub(crate) struct ParamInTyOfConstParam {
 #[diag(resolve_self_in_generic_param_default, code = E0735)]
 pub(crate) struct SelfInGenericParamDefault {
     #[primary_span]
-    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_in_const_generic_ty)]
+pub(crate) struct SelfInConstGenericTy {
+    #[primary_span]
     pub(crate) span: Span,
 }
 
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index d9776be4dd0..5f0a2a597e9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1117,13 +1117,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         debug!("validate_res_from_ribs({:?})", res);
         let ribs = &all_ribs[rib_index + 1..];
 
-        // An invalid forward use of a generic parameter from a previous default.
-        if let RibKind::ForwardGenericParamBan = all_ribs[rib_index].kind {
+        // An invalid forward use of a generic parameter from a previous default
+        // or in a const param ty.
+        if let RibKind::ForwardGenericParamBan(reason) = all_ribs[rib_index].kind {
             if let Some(span) = finalize {
                 let res_error = if rib_ident.name == kw::SelfUpper {
-                    ResolutionError::SelfInGenericParamDefault
+                    ResolutionError::ForwardDeclaredSelf(reason)
                 } else {
-                    ResolutionError::ForwardDeclaredGenericParam
+                    ResolutionError::ForwardDeclaredGenericParam(rib_ident.name, reason)
                 };
                 self.report_error(span, res_error);
             }
@@ -1131,17 +1132,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             return Res::Err;
         }
 
-        if let RibKind::ConstParamTy = all_ribs[rib_index].kind {
-            if let Some(span) = finalize {
-                self.report_error(
-                    span,
-                    ResolutionError::ParamInTyOfConstParam { name: rib_ident.name },
-                );
-            }
-            assert_eq!(res, Res::Err);
-            return Res::Err;
-        }
-
         match res {
             Res::Local(_) => {
                 use ResolutionError::*;
@@ -1153,7 +1143,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::FnOrCoroutine
                         | RibKind::Module(..)
                         | RibKind::MacroDefinition(..)
-                        | RibKind::ForwardGenericParamBan => {
+                        | RibKind::ForwardGenericParamBan(_) => {
                             // Nothing to do. Continue.
                         }
                         RibKind::Item(..) | RibKind::AssocItem => {
@@ -1247,12 +1237,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::MacroDefinition(..)
                         | RibKind::InlineAsmSym
                         | RibKind::AssocItem
-                        | RibKind::ConstParamTy
-                        | RibKind::ForwardGenericParamBan => {
+                        | RibKind::ForwardGenericParamBan(_) => {
                             // Nothing to do. Continue.
                             continue;
                         }
 
+                        RibKind::ConstParamTy => {
+                            if !self.tcx.features().generic_const_parameter_types() {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInTyOfConstParam {
+                                            name: rib_ident.name,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            } else {
+                                continue;
+                            }
+                        }
+
                         RibKind::ConstantItem(trivial, _) => {
                             if let ConstantHasGenerics::No(cause) = trivial {
                                 // HACK(min_const_generics): If we encounter `Self` in an anonymous
@@ -1325,8 +1330,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::MacroDefinition(..)
                         | RibKind::InlineAsmSym
                         | RibKind::AssocItem
-                        | RibKind::ConstParamTy
-                        | RibKind::ForwardGenericParamBan => continue,
+                        | RibKind::ForwardGenericParamBan(_) => continue,
+
+                        RibKind::ConstParamTy => {
+                            if !self.tcx.features().generic_const_parameter_types() {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInTyOfConstParam {
+                                            name: rib_ident.name,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            } else {
+                                continue;
+                            }
+                        }
 
                         RibKind::ConstantItem(trivial, _) => {
                             if let ConstantHasGenerics::No(cause) = trivial {
@@ -1377,6 +1397,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             }
             _ => {}
         }
+
         res
     }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 2c3e4bb505c..f3f6c551580 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -207,7 +207,7 @@ pub(crate) enum RibKind<'ra> {
     /// All bindings in this rib are generic parameters that can't be used
     /// from the default of a generic parameter because they're not declared
     /// before said generic parameter. Also see the `visit_generics` override.
-    ForwardGenericParamBan,
+    ForwardGenericParamBan(ForwardGenericParamBanReason),
 
     /// We are inside of the type of a const parameter. Can't refer to any
     /// parameters.
@@ -218,6 +218,12 @@ pub(crate) enum RibKind<'ra> {
     InlineAsmSym,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub(crate) enum ForwardGenericParamBanReason {
+    Default,
+    ConstParamTy,
+}
+
 impl RibKind<'_> {
     /// Whether this rib kind contains generic parameters, as opposed to local
     /// variables.
@@ -232,7 +238,7 @@ impl RibKind<'_> {
             RibKind::ConstParamTy
             | RibKind::AssocItem
             | RibKind::Item(..)
-            | RibKind::ForwardGenericParamBan => true,
+            | RibKind::ForwardGenericParamBan(_) => true,
         }
     }
 
@@ -246,7 +252,7 @@ impl RibKind<'_> {
             | RibKind::Item(..)
             | RibKind::ConstantItem(..)
             | RibKind::Module(..)
-            | RibKind::ForwardGenericParamBan
+            | RibKind::ForwardGenericParamBan(_)
             | RibKind::ConstParamTy
             | RibKind::InlineAsmSym => true,
         }
@@ -1561,8 +1567,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         // provide previous type parameters as they're built. We
         // put all the parameters on the ban list and then remove
         // them one by one as they are processed and become available.
-        let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
-        let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
+        let mut forward_ty_ban_rib =
+            Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
+        let mut forward_const_ban_rib =
+            Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
         for param in params.iter() {
             match param.kind {
                 GenericParamKind::Type { .. } => {
@@ -1593,16 +1601,24 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
+        // NOTE: We use different ribs here not for a technical reason, but just
+        // for better diagnostics.
         let mut forward_ty_ban_rib_const_param_ty = Rib {
             bindings: forward_ty_ban_rib.bindings.clone(),
             patterns_with_skipped_bindings: FxHashMap::default(),
-            kind: RibKind::ConstParamTy,
+            kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
         };
         let mut forward_const_ban_rib_const_param_ty = Rib {
             bindings: forward_const_ban_rib.bindings.clone(),
             patterns_with_skipped_bindings: FxHashMap::default(),
-            kind: RibKind::ConstParamTy,
+            kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
         };
+        // We'll ban these with a `ConstParamTy` rib, so just clear these ribs for better
+        // diagnostics, so we don't mention anything about const param tys having generics at all.
+        if !self.r.tcx.features().generic_const_parameter_types() {
+            forward_ty_ban_rib_const_param_ty.bindings.clear();
+            forward_const_ban_rib_const_param_ty.bindings.clear();
+        }
 
         self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
             for param in params {
@@ -1628,9 +1644,7 @@ 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);
-                        if this.r.tcx.features().generic_const_parameter_types() {
-                            forward_ty_ban_rib_const_param_ty.bindings.remove(i);
-                        }
+                        forward_ty_ban_rib_const_param_ty.bindings.remove(i);
                     }
                     GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                         // Const parameters can't have param bounds.
@@ -1641,9 +1655,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         if this.r.tcx.features().generic_const_parameter_types() {
                             this.visit_ty(ty)
                         } else {
+                            this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
+                            this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
                             this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
                                 this.visit_ty(ty)
                             });
+                            this.ribs[TypeNS].pop().unwrap();
+                            this.ribs[ValueNS].pop().unwrap();
                         }
                         forward_const_ban_rib_const_param_ty = this.ribs[ValueNS].pop().unwrap();
                         forward_ty_ban_rib_const_param_ty = this.ribs[TypeNS].pop().unwrap();
@@ -1662,9 +1680,7 @@ 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);
-                        if this.r.tcx.features().generic_const_parameter_types() {
-                            forward_const_ban_rib_const_param_ty.bindings.remove(i);
-                        }
+                        forward_const_ban_rib_const_param_ty.bindings.remove(i);
                     }
                 }
             }
@@ -5101,12 +5117,18 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> {
 }
 
 impl ItemInfoCollector<'_, '_, '_> {
-    fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) {
+    fn collect_fn_info(
+        &mut self,
+        header: FnHeader,
+        decl: &FnDecl,
+        id: NodeId,
+        attrs: &[Attribute],
+    ) {
         let sig = DelegationFnSig {
-            header: sig.header,
-            param_count: sig.decl.inputs.len(),
-            has_self: sig.decl.has_self(),
-            c_variadic: sig.decl.c_variadic(),
+            header,
+            param_count: decl.inputs.len(),
+            has_self: decl.has_self(),
+            c_variadic: decl.c_variadic(),
             target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
         };
         self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
@@ -5126,7 +5148,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
             | ItemKind::Trait(box Trait { generics, .. })
             | ItemKind::TraitAlias(generics, _) => {
                 if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
-                    self.collect_fn_info(sig, item.id, &item.attrs);
+                    self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
                 }
 
                 let def_id = self.r.local_def_id(item.id);
@@ -5138,8 +5160,17 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
                 self.r.item_generics_num_lifetimes.insert(def_id, count);
             }
 
+            ItemKind::ForeignMod(ForeignMod { extern_span, safety: _, abi, items }) => {
+                for foreign_item in items {
+                    if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind {
+                        let new_header =
+                            FnHeader { ext: Extern::from_abi(*abi, *extern_span), ..sig.header };
+                        self.collect_fn_info(new_header, &sig.decl, foreign_item.id, &item.attrs);
+                    }
+                }
+            }
+
             ItemKind::Mod(..)
-            | ItemKind::ForeignMod(..)
             | ItemKind::Static(..)
             | ItemKind::Use(..)
             | ItemKind::ExternCrate(..)
@@ -5159,7 +5190,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
 
     fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
         if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
-            self.collect_fn_info(sig, item.id, &item.attrs);
+            self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
         }
         visit::walk_assoc_item(self, item, ctxt);
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ccdca855232..495ce843fcd 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -20,7 +20,6 @@
 #![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::cell::{Cell, RefCell};
@@ -32,7 +31,10 @@ use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use effective_visibilities::EffectiveVisibilitiesVisitor;
 use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
 use imports::{Import, ImportData, ImportKind, NameResolution};
-use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
+use late::{
+    ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource,
+    UnnecessaryQualification,
+};
 use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use rustc_arena::{DroplessArena, TypedArena};
 use rustc_ast::expand::StrippedCfgItem;
@@ -273,7 +275,7 @@ enum ResolutionError<'ra> {
         shadowed_binding_span: Span,
     },
     /// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
-    ForwardDeclaredGenericParam,
+    ForwardDeclaredGenericParam(Symbol, ForwardGenericParamBanReason),
     // FIXME(generic_const_parameter_types): This should give custom output specifying it's only
     // problematic to use *forward declared* parameters when the feature is enabled.
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
@@ -287,7 +289,7 @@ enum ResolutionError<'ra> {
     /// This error is emitted even with `generic_const_exprs`.
     ParamInEnumDiscriminant { name: Symbol, param_kind: ParamKindInEnumDiscriminant },
     /// Error E0735: generic parameters with a default cannot use `Self`
-    SelfInGenericParamDefault,
+    ForwardDeclaredSelf(ForwardGenericParamBanReason),
     /// Error E0767: use of unreachable label
     UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
     /// Error E0323, E0324, E0325: mismatch between trait item and impl item.
diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs
index 55be931bcd6..c4a9cab24d0 100644
--- a/compiler/rustc_sanitizers/src/lib.rs
+++ b/compiler/rustc_sanitizers/src/lib.rs
@@ -4,8 +4,8 @@
 //! compiler.
 
 // tidy-alphabetical-start
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(let_chains)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod cfi;
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 9e9b78cfdd5..13c1a273eb8 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,7 +14,6 @@
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7af221c9607..dcdb7fa9c10 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1214,7 +1214,7 @@ impl Default for Options {
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
             search_paths: vec![],
-            maybe_sysroot: None,
+            sysroot: filesearch::materialize_sysroot(None),
             target_triple: TargetTuple::from_tuple(host_tuple()),
             test: false,
             incremental: None,
@@ -2618,7 +2618,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         describe_lints,
         output_types,
         search_paths,
-        maybe_sysroot: Some(sysroot),
+        sysroot,
         target_triple,
         test,
         incremental,
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index cc2decc2fe4..50f09c57107 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -160,8 +160,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
 
 pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
     let target = crate::config::host_tuple();
-    let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
-        smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
+    let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()];
     let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string()));
     if let Ok(dll) = path {
         // use `parent` twice to chop off the file name and then also the
@@ -195,12 +194,12 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
 /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
 /// Panics if [`get_or_default_sysroot`]  returns an error.
 pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
-    maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot().expect("Failed finding sysroot"))
+    maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot())
 }
 
 /// This function checks if sysroot is found using env::args().next(), and if it
 /// is not found, finds sysroot from current rustc_driver dll.
-pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
+pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks. If the resolved path is relative, make it absolute.
     fn canonicalize(path: PathBuf) -> PathBuf {
         let path = try_canonicalize(&path).unwrap_or(path);
@@ -255,30 +254,25 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
     // binary able to locate Rust libraries in systems using content-addressable
     // storage (CAS).
     fn from_env_args_next() -> Option<PathBuf> {
-        match env::args_os().next() {
-            Some(first_arg) => {
-                let mut p = PathBuf::from(first_arg);
-
-                // Check if sysroot is found using env::args().next() only if the rustc in argv[0]
-                // is a symlink (see #79253). We might want to change/remove it to conform with
-                // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the
-                // future.
-                if fs::read_link(&p).is_err() {
-                    // Path is not a symbolic link or does not exist.
-                    return None;
-                }
-
-                // Pop off `bin/rustc`, obtaining the suspected sysroot.
-                p.pop();
-                p.pop();
-                // Look for the target rustlib directory in the suspected sysroot.
-                let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
-                rustlib_path.pop(); // pop off the dummy target.
-                rustlib_path.exists().then_some(p)
-            }
-            None => None,
+        let mut p = PathBuf::from(env::args_os().next()?);
+
+        // Check if sysroot is found using env::args().next() only if the rustc in argv[0]
+        // is a symlink (see #79253). We might want to change/remove it to conform with
+        // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the
+        // future.
+        if fs::read_link(&p).is_err() {
+            // Path is not a symbolic link or does not exist.
+            return None;
         }
+
+        // Pop off `bin/rustc`, obtaining the suspected sysroot.
+        p.pop();
+        p.pop();
+        // Look for the target rustlib directory in the suspected sysroot.
+        let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
+        rustlib_path.pop(); // pop off the dummy target.
+        rustlib_path.exists().then_some(p)
     }
 
-    Ok(from_env_args_next().unwrap_or(default_from_rustc_driver_dll()?))
+    from_env_args_next().unwrap_or(default_from_rustc_driver_dll().expect("Failed finding sysroot"))
 }
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index d432e84fdb2..0e19b982a13 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -7,7 +7,6 @@
 // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
 // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").
 #![recursion_limit = "256"]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod errors;
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 8977365ee73..804b46a9bec 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -333,7 +333,7 @@ top_level_options!(
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
         libs: Vec<NativeLib> [TRACKED],
-        maybe_sysroot: Option<PathBuf> [UNTRACKED],
+        sysroot: PathBuf [UNTRACKED],
 
         target_triple: TargetTuple [TRACKED],
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index bcd9a73d9d3..1c9adea281d 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -143,7 +143,6 @@ pub struct Session {
     pub target: Target,
     pub host: Target,
     pub opts: config::Options,
-    pub host_tlib_path: Arc<SearchPath>,
     pub target_tlib_path: Arc<SearchPath>,
     pub psess: ParseSess,
     pub sysroot: PathBuf,
@@ -1042,6 +1041,7 @@ pub fn build_session(
 
     let host_triple = config::host_tuple();
     let target_triple = sopts.target_triple.tuple();
+    // FIXME use host sysroot?
     let host_tlib_path = Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
     let target_tlib_path = if host_triple == target_triple {
         // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
@@ -1070,7 +1070,6 @@ pub fn build_session(
         target,
         host,
         opts: sopts,
-        host_tlib_path,
         target_tlib_path,
         psess,
         sysroot,
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 2215e2f01ad..eaba14bbf30 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -9,13 +9,13 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::usage_of_ty_tykind)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(allow(unused_variables), deny(warnings)))
 )]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod rustc_internal;
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index acd3b758351..aa1921fc8e7 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -272,7 +272,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let did = tables[def_id];
         let attrs_iter = if let Some(did) = did.as_local() {
-            tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter()
+            tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)).iter()
         } else {
             tcx.attrs_for_def(did).iter()
         };
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 798e186a94b..f19d4d9f362 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -32,7 +32,6 @@
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 #![feature(slice_as_chunks)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 // The code produced by the `Encodable`/`Decodable` derive macros refer to
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 4312c82815c..c4558b5ce8b 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -89,11 +89,11 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_hir::def::DefKind;
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 7ebe96960ed..a8d7da5692d 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -16,7 +16,6 @@
 #![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::path::{Path, PathBuf};
diff --git a/compiler/rustc_target/src/spec/base/fuchsia.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs
index 9deafcac27f..92cb0299ddb 100644
--- a/compiler/rustc_target/src/spec/base/fuchsia.rs
+++ b/compiler/rustc_target/src/spec/base/fuchsia.rs
@@ -7,7 +7,7 @@ pub(crate) fn opts() -> TargetOptions {
     // now. When using clang as the linker it will supply these options for us,
     // so we only list them for ld/lld.
     //
-    // https://github.com/llvm/llvm-project/blob/db9322b2066c55254e7691efeab863f43bfcc084/clang/lib/Driver/ToolChains/Fuchsia.cpp#L31
+    // https://github.com/llvm/llvm-project/blob/0419db6b95e246fe9dc90b5795beb77c393eb2ce/clang/lib/Driver/ToolChains/Fuchsia.cpp#L32
     let pre_link_args = TargetOptions::link_args(
         LinkerFlavor::Gnu(Cc::No, Lld::No),
         &[
@@ -18,9 +18,13 @@ pub(crate) fn opts() -> TargetOptions {
             "-z",
             "now",
             "-z",
+            "start-stop-visibility=hidden",
+            "-z",
             "rodynamic",
             "-z",
             "separate-loadable-segments",
+            "-z",
+            "rel",
             "--pack-dyn-relocs=relr",
         ],
     );
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
index 23ed92e62b8..8366b6d9bd8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
@@ -1,6 +1,28 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
+    let mut base = base::fuchsia::opts();
+    base.cpu = "generic".into();
+    base.features = "+v8a,+crc,+aes,+sha2,+neon".into();
+    base.max_atomic_width = Some(128);
+    base.stack_probes = StackProbeType::Inline;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::SHADOWCALLSTACK;
+    base.supports_xray = true;
+
+    base.add_pre_link_args(
+        LinkerFlavor::Gnu(Cc::No, Lld::No),
+        &[
+            "--execute-only",
+            // Enable the Cortex-A53 errata 843419 mitigation by default
+            "--fix-cortex-a53-843419",
+        ],
+    );
+
     Target {
         llvm_target: "aarch64-unknown-fuchsia".into(),
         metadata: TargetMetadata {
@@ -12,14 +34,6 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
-        options: TargetOptions {
-            features: "+v8a".into(),
-            max_atomic_width: Some(128),
-            stack_probes: StackProbeType::Inline,
-            supported_sanitizers: SanitizerSet::ADDRESS
-                | SanitizerSet::CFI
-                | SanitizerSet::SHADOWCALLSTACK,
-            ..base::fuchsia::opts()
-        },
+        options: base,
     }
 }
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 55dc6a70627..8a4bc58e546 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
@@ -2,7 +2,7 @@ use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
-        llvm_target: "riscv32".into(),
+        llvm_target: "riscv32-unknown-linux-gnu".into(),
         metadata: TargetMetadata {
             description: None,
             tier: Some(3),
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 58ded24b9c5..39aa70035e4 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
@@ -2,7 +2,7 @@ use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
-        llvm_target: "riscv64".into(),
+        llvm_target: "riscv64-unknown-linux-gnu".into(),
         metadata: TargetMetadata {
             description: None,
             tier: Some(3),
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 d673936f5f8..e260237ca77 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -1,6 +1,16 @@
-use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{CodeModel, SanitizerSet, StackProbeType, Target, TargetMetadata, base};
 
 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.llvm_abiname = "lp64d".into();
+    base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
+    base.supported_sanitizers = SanitizerSet::SHADOWCALLSTACK;
+    base.supports_xray = true;
+
     Target {
         llvm_target: "riscv64-unknown-fuchsia".into(),
         metadata: TargetMetadata {
@@ -12,14 +22,6 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
-        options: TargetOptions {
-            code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
-            llvm_abiname: "lp64d".into(),
-            max_atomic_width: Some(64),
-            supported_sanitizers: SanitizerSet::SHADOWCALLSTACK,
-            ..base::fuchsia::opts()
-        },
+        options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index d41c696ac23..d7253da7e8d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -4,7 +4,10 @@ pub(crate) fn target() -> Target {
     let mut base = base::fuchsia::opts();
     base.cpu = "x86-64".into();
     base.plt_by_default = false;
-    base.max_atomic_width = Some(64);
+    // See https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0073_x86_64_platform_requirement,
+    // which corresponds to x86-64-v2.
+    base.features = "+cx16,+sahf,+popcnt,+sse3,+sse4.1,+sse4.2,+ssse3".into();
+    base.max_atomic_width = Some(128);
     base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK;
     base.supports_xray = true;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 42d37418fb8..baf2489b2b8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -509,7 +509,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 hir::MatchSource::TryDesugar(scrut_hir_id),
             ) => {
                 if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                    let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                    let scrut_expr = self.tcx.hir_expect_expr(scrut_hir_id);
                     let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
                         let arg_expr = args.first().expect("try desugaring call w/out arg");
                         self.typeck_results
@@ -548,7 +548,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }) => match source {
                 hir::MatchSource::TryDesugar(scrut_hir_id) => {
                     if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                        let scrut_expr = self.tcx.hir_expect_expr(scrut_hir_id);
                         let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
                             let arg_expr = args.first().expect("try desugaring call w/out arg");
                             self.typeck_results
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 a6d8eb6add7..40958ec1088 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
@@ -1351,7 +1351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             && !has_impl_trait(def_id)
             // FIXME(fn_delegation): In delegation item argument spans are equal to last path
             // segment. This leads to ICE's when emitting `multipart_suggestion`.
-            && tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
+            && tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
         {
             let successor =
                 method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 51b2a0b36bb..5583deda99a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -743,7 +743,7 @@ fn foo(&self) -> Self::T { String::new() }
         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                tcx.hir().expect_opaque_ty(opaque_local_def_id)
+                tcx.hir_expect_opaque_ty(opaque_local_def_id)
             } else {
                 return false;
             };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index fecb38ab597..c7f0a88f951 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -1023,7 +1023,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 format!(" for lifetime parameter `{name}`")
             }
             infer::UpvarRegion(ref upvar_id, _) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                let var_name = self.tcx.hir_name(upvar_id.var_path.hir_id);
                 format!(" for capture of `{var_name}` by closure")
             }
             infer::Nll(..) => bug!("NLL variable found in lexical phase"),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index a7e68e6419d..cdbb92f4c7b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -778,8 +778,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let exp_local_id = exp_def_id.as_local()?;
 
                 match (
-                    &self.tcx.hir().expect_opaque_ty(last_local_id),
-                    &self.tcx.hir().expect_opaque_ty(exp_local_id),
+                    &self.tcx.hir_expect_opaque_ty(last_local_id),
+                    &self.tcx.hir_expect_opaque_ty(exp_local_id),
                 ) {
                     (
                         hir::OpaqueTy { bounds: last_bounds, .. },
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 ad46a15a5ac..dce85b43df1 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -22,12 +22,11 @@ use rustc_hir::{
     expr_needs_parens, is_range_literal,
 };
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_middle::hir::map;
 use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::print::{
     PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
-    with_forced_trimmed_paths, with_no_trimmed_paths,
+    with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion,
 };
 use rustc_middle::ty::{
     self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
@@ -93,7 +92,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
     fn get_from_await_ty<F>(
         &self,
         visitor: AwaitsVisitor,
-        hir: map::Map<'tcx>,
+        tcx: TyCtxt<'tcx>,
         ty_matches: F,
     ) -> Option<Span>
     where
@@ -102,7 +101,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
         visitor
             .awaits
             .into_iter()
-            .map(|id| hir.expect_expr(id))
+            .map(|id| tcx.hir_expect_expr(id))
             .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(await_expr))))
             .map(|expr| expr.span)
     }
@@ -111,7 +110,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
     (
         generics.tail_span_for_predicate_suggestion(),
-        format!("{} {}", generics.add_where_or_trailing_comma(), pred),
+        with_types_for_suggestion!(format!("{} {}", generics.add_where_or_trailing_comma(), pred)),
     )
 }
 
@@ -137,7 +136,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
     if hir_generics.where_clause_span.from_expansion()
         || hir_generics.where_clause_span.desugaring_kind().is_some()
         || projection.is_some_and(|projection| {
-            tcx.is_impl_trait_in_trait(projection.def_id)
+            (tcx.is_impl_trait_in_trait(projection.def_id)
+                && !tcx.features().return_type_notation())
                 || tcx.lookup_stability(projection.def_id).is_some_and(|stab| stab.is_unstable())
         })
     {
@@ -2180,8 +2180,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         err: &mut Diag<'_, G>,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
-        let hir = self.tcx.hir();
-
         // Attempt to detect an async-await error by looking at the obligation causes, looking
         // for a coroutine to be present.
         //
@@ -2350,7 +2348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let mut interior_or_upvar_span = None;
 
-        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, hir, ty_matches);
+        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, self.tcx, ty_matches);
         debug!(?from_awaited_ty);
 
         // Avoid disclosing internal information to downstream crates.
@@ -2428,7 +2426,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         // Special case the primary error message when send or sync is the trait that was
         // not implemented.
-        let hir = self.tcx.hir();
         let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
             self.tcx.get_diagnostic_name(trait_pred.def_id())
         {
@@ -2455,7 +2452,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             .parent(coroutine_did)
                             .as_local()
                             .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                            .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("future returned by `{name}` is not {trait_name}")
                             })?,
@@ -2479,7 +2476,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             .parent(coroutine_did)
                             .as_local()
                             .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                            .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("async iterator returned by `{name}` is not {trait_name}")
                             })?,
@@ -2502,7 +2499,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 .parent(coroutine_did)
                                 .as_local()
                                 .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                                .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                                 .map(|name| {
                                     format!("iterator returned by `{name}` is not {trait_name}")
                                 })?
@@ -3569,7 +3566,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
                     let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
-                    let expr = tcx.hir().expect_expr(hir_id);
+                    let expr = tcx.hir_expect_expr(hir_id);
                     (expr_ty, expr)
                 } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
                     && let body = tcx.hir_body(body_id)
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index b235d0da83c..b18fb0fb8fd 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -31,7 +31,6 @@
 #![feature(unwrap_infallible)]
 #![feature(yeet_expr)]
 #![recursion_limit = "512"] // For rustdoc
-#![warn(unreachable_pub)] // For rustdoc
 // tidy-alphabetical-end
 
 pub mod error_reporting;
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 4f177df89e2..352ac7c1a4e 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -440,7 +440,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             match (child_mode, nested_goal.source()) {
                 (
                     ChildMode::Trait(_) | ChildMode::Host(_),
-                    GoalSource::Misc | GoalSource::NormalizeGoal(_),
+                    GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
                 ) => {
                     continue;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 6db97fc321a..4cd6781ab89 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -463,18 +463,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
 
             assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive);
-            let trait_ref =
-                self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
-            let trait_obligations = self.impl_or_trait_obligations(
-                &cause,
-                obligation.recursion_depth + 1,
-                obligation.param_env,
-                trait_def_id,
-                trait_ref.args,
-                obligation.predicate,
-            );
 
-            let mut obligations = self.collect_predicates_for_types(
+            let obligations = self.collect_predicates_for_types(
                 obligation.param_env,
                 cause,
                 obligation.recursion_depth + 1,
@@ -482,10 +472,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 nested,
             );
 
-            // Adds the predicates from the trait. Note that this contains a `Self: Trait`
-            // predicate as usual. It won't have any effect since auto traits are coinductive.
-            obligations.extend(trait_obligations);
-
             debug!(?obligations, "vtable_auto_impl");
 
             obligations
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index cc329ca3328..4a889abfc28 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -70,7 +70,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
                 infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
-        return Err(CodegenObligationError::FulfillmentError);
+        return Err(CodegenObligationError::Unimplemented);
     }
 
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index d2f979bd6d9..697c8391803 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -2,7 +2,6 @@
 
 // tidy-alphabetical-start
 #![recursion_limit = "256"]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod codegen;
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 81a11f7cfb2..7d800e49ff4 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -1,6 +1,6 @@
 // tidy-alphabetical-start
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![feature(never_type)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index c84055f5b84..b7684e85d41 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -21,7 +21,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     match item.kind {
         hir::ItemKind::Trait(.., trait_item_refs) => {
             // We collect RPITITs for each trait method's return type and create a
@@ -96,7 +96,7 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId>
 fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
     let id = tcx.local_def_id_to_hir_id(def_id);
     let parent_def_id = tcx.hir_get_parent_item(id);
-    let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
+    let parent_item = tcx.hir_expect_item(parent_def_id.def_id);
     match parent_item.kind {
         hir::ItemKind::Impl(impl_) => {
             if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.owner_id.def_id == def_id)
@@ -201,7 +201,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
             let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
 
-            if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
+            if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
                 visitor.visit_fn_ret_ty(output);
 
                 tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 6205578bf74..aeaa83c77b5 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -161,7 +161,7 @@ fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Spa
 }
 
 fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     if let hir::ItemKind::Impl(impl_) = item.kind {
         let trait_args = impl_
             .of_trait
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 6dc5a9c4a47..90b3517eded 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -107,11 +107,9 @@ fn resolve_associated_item<'tcx>(
     let input = typing_env.as_query_input(trait_ref);
     let vtbl = match tcx.codegen_select_candidate(input) {
         Ok(vtbl) => vtbl,
-        Err(
-            CodegenObligationError::Ambiguity
-            | CodegenObligationError::Unimplemented
-            | CodegenObligationError::FulfillmentError,
-        ) => return Ok(None),
+        Err(CodegenObligationError::Ambiguity | CodegenObligationError::Unimplemented) => {
+            return Ok(None);
+        }
         Err(CodegenObligationError::UnconstrainedParam(guar)) => return Err(guar),
     };
 
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 8be1611bb9a..143b7d53880 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -6,6 +6,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -16,7 +17,6 @@
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index a107925fb18..3aad97d86cc 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -187,7 +187,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         if !hir_id.is_owner() {
             return;
         }
-        let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else {
+        let Some(defines) = self.tcx.hir_attr_map(hir_id.owner).define_opaque else {
             return;
         };
         for &(span, define) in defines {
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 15ef4e7d6c1..e2dfd9173fa 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -6,7 +6,6 @@
     feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
 )]
 #![cfg_attr(feature = "nightly", allow(internal_features))]
-#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate self as rustc_type_ir;
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 18e84db5d68..9ae83928057 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -13,6 +13,7 @@
 /// behavior as long as the resulting behavior is still correct.
 use std::cmp::Ordering;
 use std::collections::BTreeMap;
+use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -20,7 +21,7 @@ use std::marker::PhantomData;
 use derive_where::derive_where;
 use rustc_index::{Idx, IndexVec};
 #[cfg(feature = "nightly")]
-use rustc_macros::HashStable_NoContext;
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use tracing::debug;
 
 use crate::data_structures::HashMap;
@@ -111,21 +112,35 @@ pub trait Delegate {
 /// In the initial iteration of a cycle, we do not yet have a provisional
 /// result. In the case we return an initial provisional result depending
 /// on the kind of cycle.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub enum PathKind {
-    Coinductive,
+    /// A path consisting of only inductive/unproductive steps. Their initial
+    /// provisional result is `Err(NoSolution)`. We currently treat them as
+    /// `PathKind::Unknown` during coherence until we're fully confident in
+    /// our approach.
     Inductive,
+    /// A path which is not be coinductive right now but we may want
+    /// to change of them to be so in the future. We return an ambiguous
+    /// result in this case to prevent people from relying on this.
+    Unknown,
+    /// A path with at least one coinductive step. Such cycles hold.
+    Coinductive,
 }
+
 impl PathKind {
     /// Returns the path kind when merging `self` with `rest`.
     ///
     /// Given an inductive path `self` and a coinductive path `rest`,
     /// the path `self -> rest` would be coinductive.
+    ///
+    /// This operation represents an ordering and would be equivalent
+    /// to `max(self, rest)`.
     fn extend(self, rest: PathKind) -> PathKind {
-        match self {
-            PathKind::Coinductive => PathKind::Coinductive,
-            PathKind::Inductive => rest,
+        match (self, rest) {
+            (PathKind::Coinductive, _) | (_, PathKind::Coinductive) => PathKind::Coinductive,
+            (PathKind::Unknown, _) | (_, PathKind::Unknown) => PathKind::Unknown,
+            (PathKind::Inductive, PathKind::Inductive) => PathKind::Inductive,
         }
     }
 }
@@ -159,9 +174,6 @@ impl UsageKind {
             }
         }
     }
-    fn and_merge(&mut self, other: impl Into<Self>) {
-        *self = self.merge(other);
-    }
 }
 
 /// For each goal we track whether the paths from this goal
@@ -297,7 +309,7 @@ impl CycleHeads {
 
             let path_from_entry = match step_kind {
                 PathKind::Coinductive => AllPathsToHeadCoinductive::Yes,
-                PathKind::Inductive => path_from_entry,
+                PathKind::Unknown | PathKind::Inductive => path_from_entry,
             };
 
             self.insert(head, path_from_entry);
@@ -305,6 +317,63 @@ impl CycleHeads {
     }
 }
 
+bitflags::bitflags! {
+    /// Tracks how nested goals have been accessed. This is necessary to disable
+    /// global cache entries if computing them would otherwise result in a cycle or
+    /// access a provisional cache entry.
+    #[derive(Debug, Clone, Copy)]
+    pub struct PathsToNested: u8 {
+        /// The initial value when adding a goal to its own nested goals.
+        const EMPTY                      = 1 << 0;
+        const INDUCTIVE                  = 1 << 1;
+        const UNKNOWN                    = 1 << 2;
+        const COINDUCTIVE                = 1 << 3;
+    }
+}
+impl From<PathKind> for PathsToNested {
+    fn from(path: PathKind) -> PathsToNested {
+        match path {
+            PathKind::Inductive => PathsToNested::INDUCTIVE,
+            PathKind::Unknown => PathsToNested::UNKNOWN,
+            PathKind::Coinductive => PathsToNested::COINDUCTIVE,
+        }
+    }
+}
+impl PathsToNested {
+    /// The implementation of this function is kind of ugly. We check whether
+    /// there currently exist 'weaker' paths in the set, if so we upgrade these
+    /// paths to at least `path`.
+    #[must_use]
+    fn extend_with(mut self, path: PathKind) -> Self {
+        match path {
+            PathKind::Inductive => {
+                if self.intersects(PathsToNested::EMPTY) {
+                    self.remove(PathsToNested::EMPTY);
+                    self.insert(PathsToNested::INDUCTIVE);
+                }
+            }
+            PathKind::Unknown => {
+                if self.intersects(PathsToNested::EMPTY | PathsToNested::INDUCTIVE) {
+                    self.remove(PathsToNested::EMPTY | PathsToNested::INDUCTIVE);
+                    self.insert(PathsToNested::UNKNOWN);
+                }
+            }
+            PathKind::Coinductive => {
+                if self.intersects(
+                    PathsToNested::EMPTY | PathsToNested::INDUCTIVE | PathsToNested::UNKNOWN,
+                ) {
+                    self.remove(
+                        PathsToNested::EMPTY | PathsToNested::INDUCTIVE | PathsToNested::UNKNOWN,
+                    );
+                    self.insert(PathsToNested::COINDUCTIVE);
+                }
+            }
+        }
+
+        self
+    }
+}
+
 /// The nested goals of each stack entry and the path from the
 /// stack entry to that nested goal.
 ///
@@ -322,15 +391,18 @@ impl CycleHeads {
 /// results from a the cycle BAB depending on the cycle root.
 #[derive_where(Debug, Default, Clone; X: Cx)]
 struct NestedGoals<X: Cx> {
-    nested_goals: HashMap<X::Input, UsageKind>,
+    nested_goals: HashMap<X::Input, PathsToNested>,
 }
 impl<X: Cx> NestedGoals<X> {
     fn is_empty(&self) -> bool {
         self.nested_goals.is_empty()
     }
 
-    fn insert(&mut self, input: X::Input, path_from_entry: UsageKind) {
-        self.nested_goals.entry(input).or_insert(path_from_entry).and_merge(path_from_entry);
+    fn insert(&mut self, input: X::Input, paths_to_nested: PathsToNested) {
+        match self.nested_goals.entry(input) {
+            Entry::Occupied(mut entry) => *entry.get_mut() |= paths_to_nested,
+            Entry::Vacant(entry) => drop(entry.insert(paths_to_nested)),
+        }
     }
 
     /// Adds the nested goals of a nested goal, given that the path `step_kind` from this goal
@@ -341,18 +413,15 @@ impl<X: Cx> NestedGoals<X> {
     /// the same as for the child.
     fn extend_from_child(&mut self, step_kind: PathKind, nested_goals: &NestedGoals<X>) {
         #[allow(rustc::potential_query_instability)]
-        for (input, path_from_entry) in nested_goals.iter() {
-            let path_from_entry = match step_kind {
-                PathKind::Coinductive => UsageKind::Single(PathKind::Coinductive),
-                PathKind::Inductive => path_from_entry,
-            };
-            self.insert(input, path_from_entry);
+        for (input, paths_to_nested) in nested_goals.iter() {
+            let paths_to_nested = paths_to_nested.extend_with(step_kind);
+            self.insert(input, paths_to_nested);
         }
     }
 
     #[cfg_attr(feature = "nightly", rustc_lint_query_instability)]
     #[allow(rustc::potential_query_instability)]
-    fn iter(&self) -> impl Iterator<Item = (X::Input, UsageKind)> {
+    fn iter(&self) -> impl Iterator<Item = (X::Input, PathsToNested)> + '_ {
         self.nested_goals.iter().map(|(i, p)| (*i, *p))
     }
 
@@ -490,7 +559,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             // goals as this change may cause them to now depend on additional
             // goals, resulting in new cycles. See the dev-guide for examples.
             if parent_depends_on_cycle {
-                parent.nested_goals.insert(parent.input, UsageKind::Single(PathKind::Inductive))
+                parent.nested_goals.insert(parent.input, PathsToNested::EMPTY);
             }
         }
     }
@@ -666,7 +735,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             //
             // We must therefore not use the global cache entry for `B` in that case.
             // See tests/ui/traits/next-solver/cycles/hidden-by-overflow.rs
-            last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Inductive));
+            last.nested_goals.insert(last.input, PathsToNested::EMPTY);
         }
 
         debug!("encountered stack overflow");
@@ -749,16 +818,11 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
 
                 // We now care about the path from the next highest cycle head to the
                 // provisional cache entry.
-                match path_from_head {
-                    PathKind::Coinductive => {}
-                    PathKind::Inductive => {
-                        *path_from_head = Self::cycle_path_kind(
-                            &self.stack,
-                            stack_entry.step_kind_from_parent,
-                            head,
-                        )
-                    }
-                }
+                *path_from_head = path_from_head.extend(Self::cycle_path_kind(
+                    &self.stack,
+                    stack_entry.step_kind_from_parent,
+                    head,
+                ));
                 // Mutate the result of the provisional cache entry in case we did
                 // not reach a fixpoint.
                 *result = mutate_result(input, *result);
@@ -858,7 +922,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             for &ProvisionalCacheEntry {
                 encountered_overflow,
                 ref heads,
-                path_from_head,
+                path_from_head: head_to_provisional,
                 result: _,
             } in entries.iter()
             {
@@ -870,24 +934,19 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
 
                 // A provisional cache entry only applies if the path from its highest head
                 // matches the path when encountering the goal.
+                //
+                // We check if any of the paths taken while computing the global goal
+                // would end up with an applicable provisional cache entry.
                 let head = heads.highest_cycle_head();
-                let full_path = match Self::cycle_path_kind(stack, step_kind_from_parent, head) {
-                    PathKind::Coinductive => UsageKind::Single(PathKind::Coinductive),
-                    PathKind::Inductive => path_from_global_entry,
-                };
-
-                match (full_path, path_from_head) {
-                    (UsageKind::Mixed, _)
-                    | (UsageKind::Single(PathKind::Coinductive), PathKind::Coinductive)
-                    | (UsageKind::Single(PathKind::Inductive), PathKind::Inductive) => {
-                        debug!(
-                            ?full_path,
-                            ?path_from_head,
-                            "cache entry not applicable due to matching paths"
-                        );
-                        return false;
-                    }
-                    _ => debug!(?full_path, ?path_from_head, "paths don't match"),
+                let head_to_curr = Self::cycle_path_kind(stack, step_kind_from_parent, head);
+                let full_paths = path_from_global_entry.extend_with(head_to_curr);
+                if full_paths.contains(head_to_provisional.into()) {
+                    debug!(
+                        ?full_paths,
+                        ?head_to_provisional,
+                        "cache entry not applicable due to matching paths"
+                    );
+                    return false;
                 }
             }
         }
@@ -986,8 +1045,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         let last = &mut self.stack[last_index];
         last.reached_depth = last.reached_depth.max(next_index);
 
-        last.nested_goals.insert(input, UsageKind::Single(step_kind_from_parent));
-        last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Inductive));
+        last.nested_goals.insert(input, step_kind_from_parent.into());
+        last.nested_goals.insert(last.input, PathsToNested::EMPTY);
         if last_index != head {
             last.heads.insert(head, step_kind_from_parent);
         }
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 6f37db1cb85..de2e0f2c0ec 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -58,20 +58,24 @@ impl<I: Interner, P> Goal<I, P> {
 /// Why a specific goal has to be proven.
 ///
 /// This is necessary as we treat nested goals different depending on
-/// their source. This is currently mostly used by proof tree visitors
-/// but will be used by cycle handling in the future.
+/// their source. This is used to decide whether a cycle is coinductive.
+/// See the documentation of `EvalCtxt::step_kind_for_source` for more details
+/// about this.
+///
+/// It is also used by proof tree visitors, e.g. for diagnostics purposes.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum GoalSource {
     Misc,
-    /// We're proving a where-bound of an impl.
+    /// A nested goal required to prove that types are equal/subtypes.
+    /// This is always an unproductive step.
     ///
-    /// FIXME(-Znext-solver=coinductive): Explain how and why this
-    /// changes whether cycles are coinductive.
+    /// This is also used for all `NormalizesTo` goals as we they are used
+    /// to relate types in `AliasRelate`.
+    TypeRelating,
+    /// We're proving a where-bound of an impl.
     ImplWhereBound,
     /// Const conditions that need to hold for `~const` alias bounds to hold.
-    ///
-    /// FIXME(-Znext-solver=coinductive): Are these even coinductive?
     AliasBoundConstCondition,
     /// Instantiating a higher-ranked goal and re-proving it.
     InstantiateHigherRanked,
@@ -79,7 +83,6 @@ pub enum GoalSource {
     /// This is used in two places: projecting to an opaque whose hidden type
     /// is already registered in the opaque type storage, and for rigid projections.
     AliasWellFormed,
-
     /// In case normalizing aliases in nested goals cycles, eagerly normalizing these
     /// aliases in the context of the parent may incorrectly change the cycle kind.
     /// Normalizing aliases in goals therefore tracks the original path kind for this
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 8f174f28472..104e0a3d010 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -157,9 +157,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.170"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 dependencies = [
  "rustc-std-workspace-core",
 ]
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index dbdf292433b..8d0253bd29a 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -8,7 +8,7 @@ repository = "https://github.com/rust-lang/rust.git"
 description = "The Rust core allocation and collections library"
 autotests = false
 autobenches = false
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = false
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 9b19ab74edf..e77caad6540 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -239,7 +239,7 @@ pub struct Box<
 /// This is the surface syntax for `box <expr>` expressions.
 #[rustc_intrinsic]
 #[unstable(feature = "liballoc_internals", issue = "none")]
-pub fn box_new<T>(_x: T) -> Box<T>;
+pub fn box_new<T>(x: T) -> Box<T>;
 
 impl<T> Box<T> {
     /// Allocates memory on the heap and then places `x` into it.
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index edde8153aa1..b60826ee4e6 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -9,7 +9,7 @@ autobenches = false
 # If you update this, be sure to update it in a bunch of other places too!
 # As of 2024, it was src/tools/opt-dist, the core-no-fp-fmt-parse test and
 # the version of the prelude imported in core/lib.rs.
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = false
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index cefa0e3950c..1ad8038cbf6 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -306,15 +306,15 @@ impl<'f> Drop for VaListImpl<'f> {
 /// `va_copy`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-unsafe fn va_end(_ap: &mut VaListImpl<'_>);
+unsafe fn va_end(ap: &mut VaListImpl<'_>);
 
 /// Copies the current location of arglist `src` to the arglist `dst`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-unsafe fn va_copy<'f>(_dest: *mut VaListImpl<'f>, _src: &VaListImpl<'f>);
+unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
 
 /// Loads an argument of type `T` from the `va_list` `ap` and increment the
 /// argument `ap` points to.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-unsafe fn va_arg<T: sealed_trait::VaArgSafe>(_ap: &mut VaListImpl<'_>) -> T;
+unsafe fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 6af647b137d..48b265fabc7 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -90,6 +90,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 // memory, which is not valid for either `&` or `&mut`.
 
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -97,8 +98,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -106,8 +108,9 @@ pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -115,8 +118,9 @@ pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -124,8 +128,9 @@ pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -133,8 +138,9 @@ pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -142,8 +148,9 @@ pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -151,8 +158,9 @@ pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -160,8 +168,9 @@ pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -169,8 +178,9 @@ pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -178,8 +188,9 @@ pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -187,8 +198,9 @@ pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -196,8 +208,9 @@ pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -205,8 +218,9 @@ pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -214,8 +228,9 @@ pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange` method by passing
@@ -223,9 +238,10 @@ pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(_dst: *mut T, _old: T, _src:
 /// For example, [`AtomicBool::compare_exchange`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchg_seqcst_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -239,6 +255,7 @@ pub unsafe fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -252,6 +269,7 @@ pub unsafe fn atomic_cxchgweak_relaxed_acquire<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -259,9 +277,9 @@ pub unsafe fn atomic_cxchgweak_relaxed_acquire<T: Copy>(
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -275,6 +293,7 @@ pub unsafe fn atomic_cxchgweak_acquire_relaxed<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -288,6 +307,7 @@ pub unsafe fn atomic_cxchgweak_acquire_acquire<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -295,9 +315,9 @@ pub unsafe fn atomic_cxchgweak_acquire_acquire<T: Copy>(
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_acquire_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -311,6 +331,7 @@ pub unsafe fn atomic_cxchgweak_release_relaxed<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -324,6 +345,7 @@ pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>(
     _src: T,
 ) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -331,9 +353,9 @@ pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>(
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -341,9 +363,9 @@ pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(_dst: *mut T, _old: T, _s
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -351,9 +373,9 @@ pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(_dst: *mut T, _old: T, _s
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -361,8 +383,9 @@ pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(_dst: *mut T, _old: T, _s
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -370,9 +393,9 @@ pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _sr
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -380,9 +403,9 @@ pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(_dst: *mut T, _old: T, _s
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T)
--> (T, bool);
+pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 /// Stores a value if the current value is the same as the `old` value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `compare_exchange_weak` method by passing
@@ -390,520 +413,641 @@ pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(_dst: *mut T, _old: T, _s
 /// For example, [`AtomicBool::compare_exchange_weak`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool);
+pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 
 /// Loads the current value of the pointer.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `load` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_load_seqcst<T: Copy>(_src: *const T) -> T;
+pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
 /// Loads the current value of the pointer.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `load` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_load_acquire<T: Copy>(_src: *const T) -> T;
+pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
 /// Loads the current value of the pointer.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `load` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_load_relaxed<T: Copy>(_src: *const T) -> T;
+pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
 /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
 /// In terms of the Rust Abstract Machine, this operation is equivalent to `src.read()`,
 /// i.e., it performs a non-atomic read.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_load_unordered<T: Copy>(_src: *const T) -> T;
+pub unsafe fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
 
 /// Stores the value at the specified memory location.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `store` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_store_seqcst<T: Copy>(_dst: *mut T, _val: T);
+pub unsafe fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
 /// Stores the value at the specified memory location.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `store` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_store_release<T: Copy>(_dst: *mut T, _val: T);
+pub unsafe fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
 /// Stores the value at the specified memory location.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `store` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_store_relaxed<T: Copy>(_dst: *mut T, _val: T);
+pub unsafe fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
 /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
 /// In terms of the Rust Abstract Machine, this operation is equivalent to `dst.write(val)`,
 /// i.e., it performs a non-atomic write.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_store_unordered<T: Copy>(_dst: *mut T, _val: T);
+pub unsafe fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
 
 /// Stores the value at the specified memory location, returning the old value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `swap` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xchg_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Stores the value at the specified memory location, returning the old value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `swap` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xchg_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Stores the value at the specified memory location, returning the old value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `swap` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xchg_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Stores the value at the specified memory location, returning the old value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `swap` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xchg_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Stores the value at the specified memory location, returning the old value.
+/// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `swap` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xchg_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Adds to the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Adds to the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Adds to the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Adds to the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Adds to the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Subtract from the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Subtract from the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Subtract from the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Subtract from the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Subtract from the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Bitwise and with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise and with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise and with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise and with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise and with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Bitwise nand with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise nand with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise nand with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise nand with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise nand with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Bitwise or with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise or with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise or with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise or with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise or with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Bitwise xor with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise xor with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise xor with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise xor with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Bitwise xor with the current value, returning the previous value.
+/// `T` must be an integer or pointer type.
+/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
+/// value stored at `*dst` will have the provenance of the old value stored there.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Maximum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_max` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_max_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_max` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_max_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_max` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_max_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_max` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_max_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
-/// Maximum with the current value.
+pub unsafe fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+/// Maximum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_max` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_max_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Minimum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_min` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_min_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_min` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_min_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_min` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_min_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_min` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_min_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using a signed comparison.
+/// `T` must be a signed integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] signed integer types via the `fetch_min` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_min_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Minimum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umin_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umin_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umin_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umin_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Minimum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umin_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// Maximum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umax_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umax_acquire<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
 /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umax_release<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
 /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umax_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
 /// Maximum with the current value using an unsigned comparison.
+/// `T` must be an unsigned integer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_umax_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T;
+pub unsafe fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
 /// An atomic fence.
 ///
@@ -1002,7 +1146,7 @@ pub unsafe fn atomic_singlethreadfence_acqrel();
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn prefetch_read_data<T>(_data: *const T, _locality: i32);
+pub unsafe fn prefetch_read_data<T>(data: *const T, locality: i32);
 /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
 /// if supported; otherwise, it is a no-op.
 /// Prefetches have no effect on the behavior of the program but can change its performance
@@ -1014,7 +1158,7 @@ pub unsafe fn prefetch_read_data<T>(_data: *const T, _locality: i32);
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn prefetch_write_data<T>(_data: *const T, _locality: i32);
+pub unsafe fn prefetch_write_data<T>(data: *const T, locality: i32);
 /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
 /// if supported; otherwise, it is a no-op.
 /// Prefetches have no effect on the behavior of the program but can change its performance
@@ -1026,7 +1170,7 @@ pub unsafe fn prefetch_write_data<T>(_data: *const T, _locality: i32);
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn prefetch_read_instruction<T>(_data: *const T, _locality: i32);
+pub unsafe fn prefetch_read_instruction<T>(data: *const T, locality: i32);
 /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
 /// if supported; otherwise, it is a no-op.
 /// Prefetches have no effect on the behavior of the program but can change its performance
@@ -1038,7 +1182,7 @@ pub unsafe fn prefetch_read_instruction<T>(_data: *const T, _locality: i32);
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32);
+pub unsafe fn prefetch_write_instruction<T>(data: *const T, locality: i32);
 
 /// Executes a breakpoint trap, for inspection by a debugger.
 ///
@@ -1539,7 +1683,7 @@ pub const fn forget<T: ?Sized>(_: T);
 #[rustc_diagnostic_item = "transmute"]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst;
+pub const unsafe fn transmute<Src, Dst>(src: Src) -> Dst;
 
 /// Like [`transmute`], but even less checked at compile-time: rather than
 /// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's
@@ -1553,7 +1697,7 @@ pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn transmute_unchecked<Src, Dst>(_src: Src) -> Dst;
+pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
 
 /// Returns `true` if the actual type given as `T` requires drop
 /// glue; returns `false` if the actual type provided for `T`
@@ -1593,7 +1737,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn offset<Ptr, Delta>(_dst: Ptr, _offset: Delta) -> Ptr;
+pub const unsafe fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 
 /// Calculates the offset from a pointer, potentially wrapping.
 ///
@@ -1612,7 +1756,7 @@ pub const unsafe fn offset<Ptr, Delta>(_dst: Ptr, _offset: Delta) -> Ptr;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T;
+pub const unsafe fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
 /// Masks out bits of the pointer according to a mask.
 ///
@@ -1624,7 +1768,7 @@ pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T;
 /// Consider using [`pointer::mask`] instead.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T;
+pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
 
 /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
 /// a size of `count` * `size_of::<T>()` and an alignment of
@@ -1636,7 +1780,7 @@ pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn volatile_copy_nonoverlapping_memory<T>(_dst: *mut T, _src: *const T, _count: usize);
+pub unsafe fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
 /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
 /// a size of `count * size_of::<T>()` and an alignment of
 /// `min_align_of::<T>()`
@@ -1647,7 +1791,7 @@ pub unsafe fn volatile_copy_nonoverlapping_memory<T>(_dst: *mut T, _src: *const
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn volatile_copy_memory<T>(_dst: *mut T, _src: *const T, _count: usize);
+pub unsafe fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
 /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
 /// size of `count * size_of::<T>()` and an alignment of
 /// `min_align_of::<T>()`.
@@ -1658,20 +1802,20 @@ pub unsafe fn volatile_copy_memory<T>(_dst: *mut T, _src: *const T, _count: usiz
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn volatile_set_memory<T>(_dst: *mut T, _val: u8, _count: usize);
+pub unsafe fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
 
 /// Performs a volatile load from the `src` pointer.
 ///
 /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn volatile_load<T>(_src: *const T) -> T;
+pub unsafe fn volatile_load<T>(src: *const T) -> T;
 /// Performs a volatile store to the `dst` pointer.
 ///
 /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn volatile_store<T>(_dst: *mut T, _val: T);
+pub unsafe fn volatile_store<T>(dst: *mut T, val: T);
 
 /// Performs a volatile load from the `src` pointer
 /// The pointer is not required to be aligned.
@@ -1680,7 +1824,7 @@ pub unsafe fn volatile_store<T>(_dst: *mut T, _val: T);
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"]
-pub unsafe fn unaligned_volatile_load<T>(_src: *const T) -> T;
+pub unsafe fn unaligned_volatile_load<T>(src: *const T) -> T;
 /// Performs a volatile store to the `dst` pointer.
 /// The pointer is not required to be aligned.
 ///
@@ -1688,7 +1832,7 @@ pub unsafe fn unaligned_volatile_load<T>(_src: *const T) -> T;
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
-pub unsafe fn unaligned_volatile_store<T>(_dst: *mut T, _val: T);
+pub unsafe fn unaligned_volatile_store<T>(dst: *mut T, val: T);
 
 /// Returns the square root of an `f16`
 ///
@@ -1696,28 +1840,28 @@ pub unsafe fn unaligned_volatile_store<T>(_dst: *mut T, _val: T);
 /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sqrtf16(_x: f16) -> f16;
+pub unsafe fn sqrtf16(x: f16) -> f16;
 /// Returns the square root of an `f32`
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sqrtf32(_x: f32) -> f32;
+pub unsafe fn sqrtf32(x: f32) -> f32;
 /// Returns the square root of an `f64`
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sqrtf64(_x: f64) -> f64;
+pub unsafe fn sqrtf64(x: f64) -> f64;
 /// Returns the square root of an `f128`
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sqrtf128(_x: f128) -> f128;
+pub unsafe fn sqrtf128(x: f128) -> f128;
 
 /// Raises an `f16` to an integer power.
 ///
@@ -1725,28 +1869,28 @@ pub unsafe fn sqrtf128(_x: f128) -> f128;
 /// [`f16::powi`](../../std/primitive.f16.html#method.powi)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powif16(_a: f16, _x: i32) -> f16;
+pub unsafe fn powif16(a: f16, x: i32) -> f16;
 /// Raises an `f32` to an integer power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::powi`](../../std/primitive.f32.html#method.powi)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powif32(_a: f32, _x: i32) -> f32;
+pub unsafe fn powif32(a: f32, x: i32) -> f32;
 /// Raises an `f64` to an integer power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::powi`](../../std/primitive.f64.html#method.powi)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powif64(_a: f64, _x: i32) -> f64;
+pub unsafe fn powif64(a: f64, x: i32) -> f64;
 /// Raises an `f128` to an integer power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::powi`](../../std/primitive.f128.html#method.powi)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powif128(_a: f128, _x: i32) -> f128;
+pub unsafe fn powif128(a: f128, x: i32) -> f128;
 
 /// Returns the sine of an `f16`.
 ///
@@ -1754,28 +1898,28 @@ pub unsafe fn powif128(_a: f128, _x: i32) -> f128;
 /// [`f16::sin`](../../std/primitive.f16.html#method.sin)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sinf16(_x: f16) -> f16;
+pub unsafe fn sinf16(x: f16) -> f16;
 /// Returns the sine of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::sin`](../../std/primitive.f32.html#method.sin)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sinf32(_x: f32) -> f32;
+pub unsafe fn sinf32(x: f32) -> f32;
 /// Returns the sine of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::sin`](../../std/primitive.f64.html#method.sin)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sinf64(_x: f64) -> f64;
+pub unsafe fn sinf64(x: f64) -> f64;
 /// Returns the sine of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::sin`](../../std/primitive.f128.html#method.sin)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn sinf128(_x: f128) -> f128;
+pub unsafe fn sinf128(x: f128) -> f128;
 
 /// Returns the cosine of an `f16`.
 ///
@@ -1783,28 +1927,28 @@ pub unsafe fn sinf128(_x: f128) -> f128;
 /// [`f16::cos`](../../std/primitive.f16.html#method.cos)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn cosf16(_x: f16) -> f16;
+pub unsafe fn cosf16(x: f16) -> f16;
 /// Returns the cosine of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::cos`](../../std/primitive.f32.html#method.cos)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn cosf32(_x: f32) -> f32;
+pub unsafe fn cosf32(x: f32) -> f32;
 /// Returns the cosine of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::cos`](../../std/primitive.f64.html#method.cos)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn cosf64(_x: f64) -> f64;
+pub unsafe fn cosf64(x: f64) -> f64;
 /// Returns the cosine of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::cos`](../../std/primitive.f128.html#method.cos)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn cosf128(_x: f128) -> f128;
+pub unsafe fn cosf128(x: f128) -> f128;
 
 /// Raises an `f16` to an `f16` power.
 ///
@@ -1812,28 +1956,28 @@ pub unsafe fn cosf128(_x: f128) -> f128;
 /// [`f16::powf`](../../std/primitive.f16.html#method.powf)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powf16(_a: f16, _x: f16) -> f16;
+pub unsafe fn powf16(a: f16, x: f16) -> f16;
 /// Raises an `f32` to an `f32` power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::powf`](../../std/primitive.f32.html#method.powf)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powf32(_a: f32, _x: f32) -> f32;
+pub unsafe fn powf32(a: f32, x: f32) -> f32;
 /// Raises an `f64` to an `f64` power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::powf`](../../std/primitive.f64.html#method.powf)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powf64(_a: f64, _x: f64) -> f64;
+pub unsafe fn powf64(a: f64, x: f64) -> f64;
 /// Raises an `f128` to an `f128` power.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::powf`](../../std/primitive.f128.html#method.powf)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn powf128(_a: f128, _x: f128) -> f128;
+pub unsafe fn powf128(a: f128, x: f128) -> f128;
 
 /// Returns the exponential of an `f16`.
 ///
@@ -1841,28 +1985,28 @@ pub unsafe fn powf128(_a: f128, _x: f128) -> f128;
 /// [`f16::exp`](../../std/primitive.f16.html#method.exp)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn expf16(_x: f16) -> f16;
+pub unsafe fn expf16(x: f16) -> f16;
 /// Returns the exponential of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::exp`](../../std/primitive.f32.html#method.exp)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn expf32(_x: f32) -> f32;
+pub unsafe fn expf32(x: f32) -> f32;
 /// Returns the exponential of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::exp`](../../std/primitive.f64.html#method.exp)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn expf64(_x: f64) -> f64;
+pub unsafe fn expf64(x: f64) -> f64;
 /// Returns the exponential of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::exp`](../../std/primitive.f128.html#method.exp)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn expf128(_x: f128) -> f128;
+pub unsafe fn expf128(x: f128) -> f128;
 
 /// Returns 2 raised to the power of an `f16`.
 ///
@@ -1870,28 +2014,28 @@ pub unsafe fn expf128(_x: f128) -> f128;
 /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn exp2f16(_x: f16) -> f16;
+pub unsafe fn exp2f16(x: f16) -> f16;
 /// Returns 2 raised to the power of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn exp2f32(_x: f32) -> f32;
+pub unsafe fn exp2f32(x: f32) -> f32;
 /// Returns 2 raised to the power of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn exp2f64(_x: f64) -> f64;
+pub unsafe fn exp2f64(x: f64) -> f64;
 /// Returns 2 raised to the power of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn exp2f128(_x: f128) -> f128;
+pub unsafe fn exp2f128(x: f128) -> f128;
 
 /// Returns the natural logarithm of an `f16`.
 ///
@@ -1899,28 +2043,28 @@ pub unsafe fn exp2f128(_x: f128) -> f128;
 /// [`f16::ln`](../../std/primitive.f16.html#method.ln)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn logf16(_x: f16) -> f16;
+pub unsafe fn logf16(x: f16) -> f16;
 /// Returns the natural logarithm of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::ln`](../../std/primitive.f32.html#method.ln)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn logf32(_x: f32) -> f32;
+pub unsafe fn logf32(x: f32) -> f32;
 /// Returns the natural logarithm of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::ln`](../../std/primitive.f64.html#method.ln)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn logf64(_x: f64) -> f64;
+pub unsafe fn logf64(x: f64) -> f64;
 /// Returns the natural logarithm of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::ln`](../../std/primitive.f128.html#method.ln)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn logf128(_x: f128) -> f128;
+pub unsafe fn logf128(x: f128) -> f128;
 
 /// Returns the base 10 logarithm of an `f16`.
 ///
@@ -1928,28 +2072,28 @@ pub unsafe fn logf128(_x: f128) -> f128;
 /// [`f16::log10`](../../std/primitive.f16.html#method.log10)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log10f16(_x: f16) -> f16;
+pub unsafe fn log10f16(x: f16) -> f16;
 /// Returns the base 10 logarithm of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::log10`](../../std/primitive.f32.html#method.log10)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log10f32(_x: f32) -> f32;
+pub unsafe fn log10f32(x: f32) -> f32;
 /// Returns the base 10 logarithm of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::log10`](../../std/primitive.f64.html#method.log10)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log10f64(_x: f64) -> f64;
+pub unsafe fn log10f64(x: f64) -> f64;
 /// Returns the base 10 logarithm of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::log10`](../../std/primitive.f128.html#method.log10)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log10f128(_x: f128) -> f128;
+pub unsafe fn log10f128(x: f128) -> f128;
 
 /// Returns the base 2 logarithm of an `f16`.
 ///
@@ -1957,28 +2101,28 @@ pub unsafe fn log10f128(_x: f128) -> f128;
 /// [`f16::log2`](../../std/primitive.f16.html#method.log2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log2f16(_x: f16) -> f16;
+pub unsafe fn log2f16(x: f16) -> f16;
 /// Returns the base 2 logarithm of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::log2`](../../std/primitive.f32.html#method.log2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log2f32(_x: f32) -> f32;
+pub unsafe fn log2f32(x: f32) -> f32;
 /// Returns the base 2 logarithm of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::log2`](../../std/primitive.f64.html#method.log2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log2f64(_x: f64) -> f64;
+pub unsafe fn log2f64(x: f64) -> f64;
 /// Returns the base 2 logarithm of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::log2`](../../std/primitive.f128.html#method.log2)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn log2f128(_x: f128) -> f128;
+pub unsafe fn log2f128(x: f128) -> f128;
 
 /// Returns `a * b + c` for `f16` values.
 ///
@@ -1986,28 +2130,28 @@ pub unsafe fn log2f128(_x: f128) -> f128;
 /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmaf16(_a: f16, _b: f16, _c: f16) -> f16;
+pub unsafe fn fmaf16(a: f16, b: f16, c: f16) -> f16;
 /// Returns `a * b + c` for `f32` values.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmaf32(_a: f32, _b: f32, _c: f32) -> f32;
+pub unsafe fn fmaf32(a: f32, b: f32, c: f32) -> f32;
 /// Returns `a * b + c` for `f64` values.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmaf64(_a: f64, _b: f64, _c: f64) -> f64;
+pub unsafe fn fmaf64(a: f64, b: f64, c: f64) -> f64;
 /// Returns `a * b + c` for `f128` values.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128;
+pub unsafe fn fmaf128(a: f128, b: f128, c: f128) -> f128;
 
 /// Returns `a * b + c` for `f16` values, non-deterministically executing
 /// either a fused multiply-add or two operations with rounding of the
@@ -2021,7 +2165,7 @@ pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128;
 /// example.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16;
+pub unsafe fn fmuladdf16(a: f16, b: f16, c: f16) -> f16;
 /// Returns `a * b + c` for `f32` values, non-deterministically executing
 /// either a fused multiply-add or two operations with rounding of the
 /// intermediate result.
@@ -2034,7 +2178,7 @@ pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16;
 /// example.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32;
+pub unsafe fn fmuladdf32(a: f32, b: f32, c: f32) -> f32;
 /// Returns `a * b + c` for `f64` values, non-deterministically executing
 /// either a fused multiply-add or two operations with rounding of the
 /// intermediate result.
@@ -2047,7 +2191,7 @@ pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32;
 /// example.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64;
+pub unsafe fn fmuladdf64(a: f64, b: f64, c: f64) -> f64;
 /// Returns `a * b + c` for `f128` values, non-deterministically executing
 /// either a fused multiply-add or two operations with rounding of the
 /// intermediate result.
@@ -2060,7 +2204,7 @@ pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64;
 /// example.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128;
+pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
 
 /// Returns the largest integer less than or equal to an `f16`.
 ///
@@ -2068,28 +2212,28 @@ pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128;
 /// [`f16::floor`](../../std/primitive.f16.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf16(_x: f16) -> f16;
+pub unsafe fn floorf16(x: f16) -> f16;
 /// Returns the largest integer less than or equal to an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::floor`](../../std/primitive.f32.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf32(_x: f32) -> f32;
+pub unsafe fn floorf32(x: f32) -> f32;
 /// Returns the largest integer less than or equal to an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::floor`](../../std/primitive.f64.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf64(_x: f64) -> f64;
+pub unsafe fn floorf64(x: f64) -> f64;
 /// Returns the largest integer less than or equal to an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::floor`](../../std/primitive.f128.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf128(_x: f128) -> f128;
+pub unsafe fn floorf128(x: f128) -> f128;
 
 /// Returns the smallest integer greater than or equal to an `f16`.
 ///
@@ -2097,28 +2241,28 @@ pub unsafe fn floorf128(_x: f128) -> f128;
 /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf16(_x: f16) -> f16;
+pub unsafe fn ceilf16(x: f16) -> f16;
 /// Returns the smallest integer greater than or equal to an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf32(_x: f32) -> f32;
+pub unsafe fn ceilf32(x: f32) -> f32;
 /// Returns the smallest integer greater than or equal to an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf64(_x: f64) -> f64;
+pub unsafe fn ceilf64(x: f64) -> f64;
 /// Returns the smallest integer greater than or equal to an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf128(_x: f128) -> f128;
+pub unsafe fn ceilf128(x: f128) -> f128;
 
 /// Returns the integer part of an `f16`.
 ///
@@ -2126,28 +2270,28 @@ pub unsafe fn ceilf128(_x: f128) -> f128;
 /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf16(_x: f16) -> f16;
+pub unsafe fn truncf16(x: f16) -> f16;
 /// Returns the integer part of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf32(_x: f32) -> f32;
+pub unsafe fn truncf32(x: f32) -> f32;
 /// Returns the integer part of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf64(_x: f64) -> f64;
+pub unsafe fn truncf64(x: f64) -> f64;
 /// Returns the integer part of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf128(_x: f128) -> f128;
+pub unsafe fn truncf128(x: f128) -> f128;
 
 /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even
 /// least significant digit.
@@ -2157,14 +2301,14 @@ pub unsafe fn truncf128(_x: f128) -> f128;
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[cfg(not(bootstrap))]
-pub fn round_ties_even_f16(_x: f16) -> f16;
+pub fn round_ties_even_f16(x: f16) -> f16;
 
 /// To be removed on next bootstrap bump.
 #[cfg(bootstrap)]
 pub fn round_ties_even_f16(x: f16) -> f16 {
     #[rustc_intrinsic]
     #[rustc_nounwind]
-    unsafe fn rintf16(_x: f16) -> f16;
+    unsafe fn rintf16(x: f16) -> f16;
 
     // SAFETY: this intrinsic isn't actually unsafe
     unsafe { rintf16(x) }
@@ -2178,14 +2322,14 @@ pub fn round_ties_even_f16(x: f16) -> f16 {
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[cfg(not(bootstrap))]
-pub fn round_ties_even_f32(_x: f32) -> f32;
+pub fn round_ties_even_f32(x: f32) -> f32;
 
 /// To be removed on next bootstrap bump.
 #[cfg(bootstrap)]
 pub fn round_ties_even_f32(x: f32) -> f32 {
     #[rustc_intrinsic]
     #[rustc_nounwind]
-    unsafe fn rintf32(_x: f32) -> f32;
+    unsafe fn rintf32(x: f32) -> f32;
 
     // SAFETY: this intrinsic isn't actually unsafe
     unsafe { rintf32(x) }
@@ -2205,14 +2349,14 @@ pub unsafe fn rintf32(x: f32) -> f32 {
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[cfg(not(bootstrap))]
-pub fn round_ties_even_f64(_x: f64) -> f64;
+pub fn round_ties_even_f64(x: f64) -> f64;
 
 /// To be removed on next bootstrap bump.
 #[cfg(bootstrap)]
 pub fn round_ties_even_f64(x: f64) -> f64 {
     #[rustc_intrinsic]
     #[rustc_nounwind]
-    unsafe fn rintf64(_x: f64) -> f64;
+    unsafe fn rintf64(x: f64) -> f64;
 
     // SAFETY: this intrinsic isn't actually unsafe
     unsafe { rintf64(x) }
@@ -2232,14 +2376,14 @@ pub unsafe fn rintf64(x: f64) -> f64 {
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[cfg(not(bootstrap))]
-pub fn round_ties_even_f128(_x: f128) -> f128;
+pub fn round_ties_even_f128(x: f128) -> f128;
 
 /// To be removed on next bootstrap bump.
 #[cfg(bootstrap)]
 pub fn round_ties_even_f128(x: f128) -> f128 {
     #[rustc_intrinsic]
     #[rustc_nounwind]
-    unsafe fn rintf128(_x: f128) -> f128;
+    unsafe fn rintf128(x: f128) -> f128;
 
     // SAFETY: this intrinsic isn't actually unsafe
     unsafe { rintf128(x) }
@@ -2251,28 +2395,28 @@ pub fn round_ties_even_f128(x: f128) -> f128 {
 /// [`f16::round`](../../std/primitive.f16.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf16(_x: f16) -> f16;
+pub unsafe fn roundf16(x: f16) -> f16;
 /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::round`](../../std/primitive.f32.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf32(_x: f32) -> f32;
+pub unsafe fn roundf32(x: f32) -> f32;
 /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::round`](../../std/primitive.f64.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf64(_x: f64) -> f64;
+pub unsafe fn roundf64(x: f64) -> f64;
 /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::round`](../../std/primitive.f128.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf128(_x: f128) -> f128;
+pub unsafe fn roundf128(x: f128) -> f128;
 
 /// Float addition that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2280,7 +2424,7 @@ pub unsafe fn roundf128(_x: f128) -> f128;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fadd_fast<T: Copy>(_a: T, _b: T) -> T;
+pub unsafe fn fadd_fast<T: Copy>(a: T, b: T) -> T;
 
 /// Float subtraction that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2288,7 +2432,7 @@ pub unsafe fn fadd_fast<T: Copy>(_a: T, _b: T) -> T;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fsub_fast<T: Copy>(_a: T, _b: T) -> T;
+pub unsafe fn fsub_fast<T: Copy>(a: T, b: T) -> T;
 
 /// Float multiplication that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2296,7 +2440,7 @@ pub unsafe fn fsub_fast<T: Copy>(_a: T, _b: T) -> T;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fmul_fast<T: Copy>(_a: T, _b: T) -> T;
+pub unsafe fn fmul_fast<T: Copy>(a: T, b: T) -> T;
 
 /// Float division that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2304,7 +2448,7 @@ pub unsafe fn fmul_fast<T: Copy>(_a: T, _b: T) -> T;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn fdiv_fast<T: Copy>(_a: T, _b: T) -> T;
+pub unsafe fn fdiv_fast<T: Copy>(a: T, b: T) -> T;
 
 /// Float remainder that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2312,7 +2456,7 @@ pub unsafe fn fdiv_fast<T: Copy>(_a: T, _b: T) -> T;
 /// This intrinsic does not have a stable counterpart.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn frem_fast<T: Copy>(_a: T, _b: T) -> T;
+pub unsafe fn frem_fast<T: Copy>(a: T, b: T) -> T;
 
 /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
 /// (<https://github.com/rust-lang/rust/issues/10184>)
@@ -2320,42 +2464,42 @@ pub unsafe fn frem_fast<T: Copy>(_a: T, _b: T) -> T;
 /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 /// Float addition that allows optimizations based on algebraic rules.
 ///
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fadd_algebraic<T: Copy>(_a: T, _b: T) -> T;
+pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float subtraction that allows optimizations based on algebraic rules.
 ///
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fsub_algebraic<T: Copy>(_a: T, _b: T) -> T;
+pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float multiplication that allows optimizations based on algebraic rules.
 ///
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fmul_algebraic<T: Copy>(_a: T, _b: T) -> T;
+pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float division that allows optimizations based on algebraic rules.
 ///
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fdiv_algebraic<T: Copy>(_a: T, _b: T) -> T;
+pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float remainder that allows optimizations based on algebraic rules.
 ///
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T;
+pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Returns the number of bits set in an integer type `T`
 ///
@@ -2370,7 +2514,7 @@ pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn ctpop<T: Copy>(_x: T) -> u32;
+pub const fn ctpop<T: Copy>(x: T) -> u32;
 
 /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
 ///
@@ -2411,7 +2555,7 @@ pub const fn ctpop<T: Copy>(_x: T) -> u32;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn ctlz<T: Copy>(_x: T) -> u32;
+pub const fn ctlz<T: Copy>(x: T) -> u32;
 
 /// Like `ctlz`, but extra-unsafe as it returns `undef` when
 /// given an `x` with value `0`.
@@ -2433,7 +2577,7 @@ pub const fn ctlz<T: Copy>(_x: T) -> u32;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn ctlz_nonzero<T: Copy>(_x: T) -> u32;
+pub const unsafe fn ctlz_nonzero<T: Copy>(x: T) -> u32;
 
 /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
 ///
@@ -2474,7 +2618,7 @@ pub const unsafe fn ctlz_nonzero<T: Copy>(_x: T) -> u32;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn cttz<T: Copy>(_x: T) -> u32;
+pub const fn cttz<T: Copy>(x: T) -> u32;
 
 /// Like `cttz`, but extra-unsafe as it returns `undef` when
 /// given an `x` with value `0`.
@@ -2496,7 +2640,7 @@ pub const fn cttz<T: Copy>(_x: T) -> u32;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn cttz_nonzero<T: Copy>(_x: T) -> u32;
+pub const unsafe fn cttz_nonzero<T: Copy>(x: T) -> u32;
 
 /// Reverses the bytes in an integer type `T`.
 ///
@@ -2511,7 +2655,7 @@ pub const unsafe fn cttz_nonzero<T: Copy>(_x: T) -> u32;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn bswap<T: Copy>(_x: T) -> T;
+pub const fn bswap<T: Copy>(x: T) -> T;
 
 /// Reverses the bits in an integer type `T`.
 ///
@@ -2526,7 +2670,7 @@ pub const fn bswap<T: Copy>(_x: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn bitreverse<T: Copy>(_x: T) -> T;
+pub const fn bitreverse<T: Copy>(x: T) -> T;
 
 /// Does a three-way comparison between the two integer arguments.
 ///
@@ -2536,7 +2680,7 @@ pub const fn bitreverse<T: Copy>(_x: T) -> T;
 ///
 /// The stabilized version of this intrinsic is [`Ord::cmp`].
 #[rustc_intrinsic]
-pub const fn three_way_compare<T: Copy>(_lhs: T, _rhss: T) -> crate::cmp::Ordering;
+pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering;
 
 /// Combine two values which have no bits in common.
 ///
@@ -2571,7 +2715,7 @@ pub const unsafe fn disjoint_bitor<T: ~const fallback::DisjointBitOr>(a: T, b: T
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn add_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool);
+pub const fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
 /// Performs checked integer subtraction
 ///
@@ -2586,7 +2730,7 @@ pub const fn add_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool);
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn sub_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool);
+pub const fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
 /// Performs checked integer multiplication
 ///
@@ -2601,7 +2745,7 @@ pub const fn sub_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool);
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn mul_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool);
+pub const fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
 /// Performs full-width multiplication and addition with a carry:
 /// `multiplier * multiplicand + addend + carry`.
@@ -2637,7 +2781,7 @@ pub const fn carrying_mul_add<T: ~const fallback::CarryingMulAdd<Unsigned = U>,
 /// This intrinsic does not have a stable counterpart.
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn exact_div<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn exact_div<T: Copy>(x: T, y: T) -> T;
 
 /// Performs an unchecked division, resulting in undefined behavior
 /// where `y == 0` or `x == T::MIN && y == -1`
@@ -2648,7 +2792,7 @@ pub const unsafe fn exact_div<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_div<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn unchecked_div<T: Copy>(x: T, y: T) -> T;
 /// Returns the remainder of an unchecked division, resulting in
 /// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
 ///
@@ -2658,7 +2802,7 @@ pub const unsafe fn unchecked_div<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_rem<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
 
 /// Performs an unchecked left shift, resulting in undefined behavior when
 /// `y < 0` or `y >= N`, where N is the width of T in bits.
@@ -2669,7 +2813,7 @@ pub const unsafe fn unchecked_rem<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(_x: T, _y: U) -> T;
+pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
 /// Performs an unchecked right shift, resulting in undefined behavior when
 /// `y < 0` or `y >= N`, where N is the width of T in bits.
 ///
@@ -2679,7 +2823,7 @@ pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(_x: T, _y: U) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(_x: T, _y: U) -> T;
+pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
 
 /// Returns the result of an unchecked addition, resulting in
 /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
@@ -2689,7 +2833,7 @@ pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(_x: T, _y: U) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_add<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn unchecked_add<T: Copy>(x: T, y: T) -> T;
 
 /// Returns the result of an unchecked subtraction, resulting in
 /// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
@@ -2699,7 +2843,7 @@ pub const unsafe fn unchecked_add<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_sub<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
 
 /// Returns the result of an unchecked multiplication, resulting in
 /// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
@@ -2709,7 +2853,7 @@ pub const unsafe fn unchecked_sub<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn unchecked_mul<T: Copy>(_x: T, _y: T) -> T;
+pub const unsafe fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
 
 /// Performs rotate left.
 ///
@@ -2724,7 +2868,7 @@ pub const unsafe fn unchecked_mul<T: Copy>(_x: T, _y: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn rotate_left<T: Copy>(_x: T, _shift: u32) -> T;
+pub const fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
 
 /// Performs rotate right.
 ///
@@ -2739,7 +2883,7 @@ pub const fn rotate_left<T: Copy>(_x: T, _shift: u32) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn rotate_right<T: Copy>(_x: T, _shift: u32) -> T;
+pub const fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
 
 /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
 ///
@@ -2754,7 +2898,7 @@ pub const fn rotate_right<T: Copy>(_x: T, _shift: u32) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn wrapping_add<T: Copy>(_a: T, _b: T) -> T;
+pub const fn wrapping_add<T: Copy>(a: T, b: T) -> T;
 /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
 ///
 /// Note that, unlike most intrinsics, this is safe to call;
@@ -2768,7 +2912,7 @@ pub const fn wrapping_add<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn wrapping_sub<T: Copy>(_a: T, _b: T) -> T;
+pub const fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
 /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
 ///
 /// Note that, unlike most intrinsics, this is safe to call;
@@ -2782,7 +2926,7 @@ pub const fn wrapping_sub<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn wrapping_mul<T: Copy>(_a: T, _b: T) -> T;
+pub const fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
 
 /// Computes `a + b`, saturating at numeric bounds.
 ///
@@ -2797,7 +2941,7 @@ pub const fn wrapping_mul<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn saturating_add<T: Copy>(_a: T, _b: T) -> T;
+pub const fn saturating_add<T: Copy>(a: T, b: T) -> T;
 /// Computes `a - b`, saturating at numeric bounds.
 ///
 /// Note that, unlike most intrinsics, this is safe to call;
@@ -2811,7 +2955,7 @@ pub const fn saturating_add<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn saturating_sub<T: Copy>(_a: T, _b: T) -> T;
+pub const fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
 /// This is an implementation detail of [`crate::ptr::read`] and should
 /// not be used anywhere else.  See its comments for why this exists.
@@ -2822,7 +2966,7 @@ pub const fn saturating_sub<T: Copy>(_a: T, _b: T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn read_via_copy<T>(_ptr: *const T) -> T;
+pub const unsafe fn read_via_copy<T>(ptr: *const T) -> T;
 
 /// This is an implementation detail of [`crate::ptr::write`] and should
 /// not be used anywhere else.  See its comments for why this exists.
@@ -2833,7 +2977,7 @@ pub const unsafe fn read_via_copy<T>(_ptr: *const T) -> T;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn write_via_move<T>(_ptr: *mut T, _value: T);
+pub const unsafe fn write_via_move<T>(ptr: *mut T, value: T);
 
 /// Returns the value of the discriminant for the variant in 'v';
 /// if `T` has no discriminant, returns `0`.
@@ -2847,7 +2991,7 @@ pub const unsafe fn write_via_move<T>(_ptr: *mut T, _value: T);
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn discriminant_value<T>(_v: &T) -> <T as DiscriminantKind>::Discriminant;
+pub const fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
 
 /// 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.
@@ -2881,19 +3025,19 @@ pub unsafe fn catch_unwind(
 /// in ways that are not allowed for regular writes).
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn nontemporal_store<T>(_ptr: *mut T, _val: T);
+pub unsafe fn nontemporal_store<T>(ptr: *mut T, val: T);
 
 /// See documentation of `<*const T>::offset_from` for details.
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn ptr_offset_from<T>(_ptr: *const T, _base: *const T) -> isize;
+pub const unsafe fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
 /// See documentation of `<*const T>::sub_ptr` for details.
 #[rustc_nounwind]
 #[rustc_intrinsic]
 #[rustc_intrinsic_const_stable_indirect]
-pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T) -> usize;
+pub const unsafe fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize;
 
 /// See documentation of `<*const T>::guaranteed_eq` for details.
 /// Returns `2` if the result is unknown.
@@ -2933,7 +3077,7 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
 /// which is UB if any of their inputs are `undef`.)
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn raw_eq<T>(_a: &T, _b: &T) -> bool;
+pub const unsafe fn raw_eq<T>(a: &T, b: &T) -> bool;
 
 /// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)`
 /// as unsigned bytes, returning negative if `left` is less, zero if all the
@@ -2951,7 +3095,7 @@ pub const unsafe fn raw_eq<T>(_a: &T, _b: &T) -> bool;
 /// [valid]: crate::ptr#safety
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: usize) -> i32;
+pub const unsafe fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32;
 
 /// See documentation of [`std::hint::black_box`] for details.
 ///
@@ -2959,7 +3103,7 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u
 #[rustc_nounwind]
 #[rustc_intrinsic]
 #[rustc_intrinsic_const_stable_indirect]
-pub const fn black_box<T>(_dummy: T) -> T;
+pub const fn black_box<T>(dummy: T) -> T;
 
 /// Selects which function to call depending on the context.
 ///
@@ -3318,7 +3462,7 @@ pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, con
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
-pub unsafe fn vtable_size(_ptr: *const ()) -> usize;
+pub unsafe fn vtable_size(ptr: *const ()) -> usize;
 
 /// The intrinsic will return the alignment stored in that vtable.
 ///
@@ -3328,7 +3472,7 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize;
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
-pub unsafe fn vtable_align(_ptr: *const ()) -> usize;
+pub unsafe fn vtable_align(ptr: *const ()) -> usize;
 
 /// The size of a type in bytes.
 ///
@@ -3395,7 +3539,7 @@ pub const fn variant_count<T>() -> usize;
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_const_stable_indirect]
-pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize;
+pub const unsafe fn size_of_val<T: ?Sized>(ptr: *const T) -> usize;
 
 /// The required alignment of the referenced value.
 ///
@@ -3408,7 +3552,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize;
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_const_stable_indirect]
-pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize;
+pub const unsafe fn min_align_of_val<T: ?Sized>(ptr: *const T) -> usize;
 
 /// Gets a static string slice containing the name of a type.
 ///
@@ -3447,7 +3591,7 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128;
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P;
+pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(data: D, meta: M) -> P;
 
 #[unstable(feature = "core_intrinsics", issue = "none")]
 pub trait AggregateRawPtr<D> {
@@ -3467,7 +3611,7 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M;
+pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const P) -> M;
 
 // Some functions are defined here because they accidentally got made
 // available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
@@ -3569,7 +3713,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
     #[rustc_intrinsic_const_stable_indirect]
     #[rustc_nounwind]
     #[rustc_intrinsic]
-    const unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize);
+    const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
     ub_checks::assert_unsafe_precondition!(
         check_language_ub,
@@ -3670,7 +3814,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     #[rustc_intrinsic_const_stable_indirect]
     #[rustc_nounwind]
     #[rustc_intrinsic]
-    const unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize);
+    const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
 
     // SAFETY: the safety contract for `copy` must be upheld by the caller.
     unsafe {
@@ -3750,7 +3894,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     #[rustc_intrinsic_const_stable_indirect]
     #[rustc_nounwind]
     #[rustc_intrinsic]
-    const unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize);
+    const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
 
     // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
     unsafe {
@@ -3778,7 +3922,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
 /// [`f16::min`]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn minnumf16(_x: f16, _y: f16) -> f16;
+pub const fn minnumf16(x: f16, y: f16) -> f16;
 
 /// Returns the minimum of two `f32` values.
 ///
@@ -3792,7 +3936,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn minnumf32(_x: f32, _y: f32) -> f32;
+pub const fn minnumf32(x: f32, y: f32) -> f32;
 
 /// Returns the minimum of two `f64` values.
 ///
@@ -3806,7 +3950,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn minnumf64(_x: f64, _y: f64) -> f64;
+pub const fn minnumf64(x: f64, y: f64) -> f64;
 
 /// Returns the minimum of two `f128` values.
 ///
@@ -3819,7 +3963,7 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64;
 /// [`f128::min`]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn minnumf128(_x: f128, _y: f128) -> f128;
+pub const fn minnumf128(x: f128, y: f128) -> f128;
 
 /// Returns the maximum of two `f16` values.
 ///
@@ -3832,7 +3976,7 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128;
 /// [`f16::max`]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn maxnumf16(_x: f16, _y: f16) -> f16;
+pub const fn maxnumf16(x: f16, y: f16) -> f16;
 
 /// Returns the maximum of two `f32` values.
 ///
@@ -3846,7 +3990,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn maxnumf32(_x: f32, _y: f32) -> f32;
+pub const fn maxnumf32(x: f32, y: f32) -> f32;
 
 /// Returns the maximum of two `f64` values.
 ///
@@ -3860,7 +4004,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn maxnumf64(_x: f64, _y: f64) -> f64;
+pub const fn maxnumf64(x: f64, y: f64) -> f64;
 
 /// Returns the maximum of two `f128` values.
 ///
@@ -3873,7 +4017,7 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64;
 /// [`f128::max`]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const fn maxnumf128(_x: f128, _y: f128) -> f128;
+pub const fn maxnumf128(x: f128, y: f128) -> f128;
 
 /// Returns the absolute value of an `f16`.
 ///
@@ -3881,7 +4025,7 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128;
 /// [`f16::abs`](../../std/primitive.f16.html#method.abs)
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn fabsf16(_x: f16) -> f16;
+pub const unsafe fn fabsf16(x: f16) -> f16;
 
 /// Returns the absolute value of an `f32`.
 ///
@@ -3890,7 +4034,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const unsafe fn fabsf32(_x: f32) -> f32;
+pub const unsafe fn fabsf32(x: f32) -> f32;
 
 /// Returns the absolute value of an `f64`.
 ///
@@ -3899,7 +4043,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const unsafe fn fabsf64(_x: f64) -> f64;
+pub const unsafe fn fabsf64(x: f64) -> f64;
 
 /// Returns the absolute value of an `f128`.
 ///
@@ -3907,7 +4051,7 @@ pub const unsafe fn fabsf64(_x: f64) -> f64;
 /// [`f128::abs`](../../std/primitive.f128.html#method.abs)
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn fabsf128(_x: f128) -> f128;
+pub const unsafe fn fabsf128(x: f128) -> f128;
 
 /// Copies the sign from `y` to `x` for `f16` values.
 ///
@@ -3915,7 +4059,7 @@ pub const unsafe fn fabsf128(_x: f128) -> f128;
 /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16;
+pub const unsafe fn copysignf16(x: f16, y: f16) -> f16;
 
 /// Copies the sign from `y` to `x` for `f32` values.
 ///
@@ -3924,7 +4068,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32;
+pub const unsafe fn copysignf32(x: f32, y: f32) -> f32;
 /// Copies the sign from `y` to `x` for `f64` values.
 ///
 /// The stabilized version of this intrinsic is
@@ -3932,7 +4076,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32;
 #[rustc_nounwind]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64;
+pub const unsafe fn copysignf64(x: f64, y: f64) -> f64;
 
 /// Copies the sign from `y` to `x` for `f128` values.
 ///
@@ -3940,7 +4084,7 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64;
 /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128;
+pub const unsafe fn copysignf128(x: f128, y: f128) -> f128;
 
 /// Inform Miri that a given pointer definitely has a certain alignment.
 #[cfg(miri)]
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index 935dd2e5673..ae6e1a779ed 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -11,7 +11,7 @@
 /// `idx` must be in-bounds of the vector.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T;
+pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
 
 /// Extracts an element from a vector.
 ///
@@ -22,28 +22,28 @@ pub const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T;
 /// `idx` must be in-bounds of the vector.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub const unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U;
+pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
 
 /// Adds two simd vectors elementwise.
 ///
 /// `T` must be a vector of integers or floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_add<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_add<T>(x: T, y: T) -> T;
 
 /// Subtracts `rhs` from `lhs` elementwise.
 ///
 /// `T` must be a vector of integers or floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_sub<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
 
 /// Multiplies two simd vectors elementwise.
 ///
 /// `T` must be a vector of integers or floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_mul<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_mul<T>(x: T, y: T) -> T;
 
 /// Divides `lhs` by `rhs` elementwise.
 ///
@@ -54,7 +54,7 @@ pub unsafe fn simd_mul<T>(_x: T, _y: T) -> T;
 /// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_div<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
 
 /// Returns remainder of two vectors elementwise.
 ///
@@ -65,7 +65,7 @@ pub unsafe fn simd_div<T>(_lhs: T, _rhs: T) -> T;
 /// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_rem<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
 
 /// Shifts vector left elementwise, with UB on overflow.
 ///
@@ -78,7 +78,7 @@ pub unsafe fn simd_rem<T>(_lhs: T, _rhs: T) -> T;
 /// Each element of `rhs` must be less than `<int>::BITS`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_shl<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
 
 /// Shifts vector right elementwise, with UB on overflow.
 ///
@@ -91,28 +91,28 @@ pub unsafe fn simd_shl<T>(_lhs: T, _rhs: T) -> T;
 /// Each element of `rhs` must be less than `<int>::BITS`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_shr<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
 
 /// "Ands" vectors elementwise.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_and<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_and<T>(x: T, y: T) -> T;
 
 /// "Ors" vectors elementwise.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_or<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_or<T>(x: T, y: T) -> T;
 
 /// "Exclusive ors" vectors elementwise.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_xor<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_xor<T>(x: T, y: T) -> T;
 
 /// Numerically casts a vector, elementwise.
 ///
@@ -133,7 +133,7 @@ pub unsafe fn simd_xor<T>(_x: T, _y: T) -> T;
 /// * Be representable in the return type, after truncating off its fractional part
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_cast<T, U>(_x: T) -> U;
+pub unsafe fn simd_cast<T, U>(x: T) -> U;
 
 /// Numerically casts a vector, elementwise.
 ///
@@ -147,7 +147,7 @@ pub unsafe fn simd_cast<T, U>(_x: T) -> U;
 /// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_as<T, U>(_x: T) -> U;
+pub unsafe fn simd_as<T, U>(x: T) -> U;
 
 /// Negates a vector elementwise.
 ///
@@ -156,14 +156,14 @@ pub unsafe fn simd_as<T, U>(_x: T) -> U;
 /// Rust panics for `-<int>::Min` due to overflow, but it is not UB with this intrinsic.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_neg<T>(_x: T) -> T;
+pub unsafe fn simd_neg<T>(x: T) -> T;
 
 /// Returns absolute value of a vector, elementwise.
 ///
 /// `T` must be a vector of floating-point primitive types.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fabs<T>(_x: T) -> T;
+pub unsafe fn simd_fabs<T>(x: T) -> T;
 
 /// Returns the minimum of two vectors, elementwise.
 ///
@@ -172,7 +172,7 @@ pub unsafe fn simd_fabs<T>(_x: T) -> T;
 /// Follows IEEE-754 `minNum` semantics.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fmin<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_fmin<T>(x: T, y: T) -> T;
 
 /// Returns the maximum of two vectors, elementwise.
 ///
@@ -181,7 +181,7 @@ pub unsafe fn simd_fmin<T>(_x: T, _y: T) -> T;
 /// Follows IEEE-754 `maxNum` semantics.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fmax<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_fmax<T>(x: T, y: T) -> T;
 
 /// Tests elementwise equality of two vectors.
 ///
@@ -192,7 +192,7 @@ pub unsafe fn simd_fmax<T>(_x: T, _y: T) -> T;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_eq<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
 
 /// Tests elementwise inequality equality of two vectors.
 ///
@@ -203,7 +203,7 @@ pub unsafe fn simd_eq<T, U>(_x: T, _y: T) -> U;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_ne<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
 
 /// Tests if `x` is less than `y`, elementwise.
 ///
@@ -214,7 +214,7 @@ pub unsafe fn simd_ne<T, U>(_x: T, _y: T) -> U;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_lt<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
 
 /// Tests if `x` is less than or equal to `y`, elementwise.
 ///
@@ -225,7 +225,7 @@ pub unsafe fn simd_lt<T, U>(_x: T, _y: T) -> U;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_le<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_le<T, U>(x: T, y: T) -> U;
 
 /// Tests if `x` is greater than `y`, elementwise.
 ///
@@ -236,7 +236,7 @@ pub unsafe fn simd_le<T, U>(_x: T, _y: T) -> U;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_gt<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
 
 /// Tests if `x` is greater than or equal to `y`, elementwise.
 ///
@@ -247,7 +247,7 @@ pub unsafe fn simd_gt<T, U>(_x: T, _y: T) -> U;
 /// Returns `0` for false and `!0` for true.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_ge<T, U>(_x: T, _y: T) -> U;
+pub unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
 
 /// Shuffles two vectors by const indices.
 ///
@@ -263,7 +263,7 @@ pub unsafe fn simd_ge<T, U>(_x: T, _y: T) -> U;
 /// of `xy`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_shuffle<T, U, V>(_x: T, _y: T, _idx: U) -> V;
+pub unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
 
 /// Reads a vector of pointers.
 ///
@@ -284,7 +284,7 @@ pub unsafe fn simd_shuffle<T, U, V>(_x: T, _y: T, _idx: U) -> V;
 /// `mask` must only contain `0` or `!0` values.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_gather<T, U, V>(_val: T, _ptr: U, _mask: V) -> T;
+pub unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
 
 /// Writes to a vector of pointers.
 ///
@@ -308,7 +308,7 @@ pub unsafe fn simd_gather<T, U, V>(_val: T, _ptr: U, _mask: V) -> T;
 /// `mask` must only contain `0` or `!0` values.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_scatter<T, U, V>(_val: T, _ptr: U, _mask: V);
+pub unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
 
 /// Reads a vector of pointers.
 ///
@@ -331,7 +331,7 @@ pub unsafe fn simd_scatter<T, U, V>(_val: T, _ptr: U, _mask: V);
 /// `mask` must only contain `0` or `!0` values.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_masked_load<V, U, T>(_mask: V, _ptr: U, _val: T) -> T;
+pub unsafe fn simd_masked_load<V, U, T>(mask: V, ptr: U, val: T) -> T;
 
 /// Writes to a vector of pointers.
 ///
@@ -353,14 +353,14 @@ pub unsafe fn simd_masked_load<V, U, T>(_mask: V, _ptr: U, _val: T) -> T;
 /// `mask` must only contain `0` or `!0` values.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_masked_store<V, U, T>(_mask: V, _ptr: U, _val: T);
+pub unsafe fn simd_masked_store<V, U, T>(mask: V, ptr: U, val: T);
 
 /// Adds two simd vectors elementwise, with saturation.
 ///
 /// `T` must be a vector of integer primitive types.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_saturating_add<T>(_x: T, _y: T) -> T;
+pub unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
 
 /// Subtracts two simd vectors elementwise, with saturation.
 ///
@@ -369,7 +369,7 @@ pub unsafe fn simd_saturating_add<T>(_x: T, _y: T) -> T;
 /// Subtract `rhs` from `lhs`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_saturating_sub<T>(_lhs: T, _rhs: T) -> T;
+pub unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
 
 /// Adds elements within a vector from left to right.
 ///
@@ -380,7 +380,7 @@ pub unsafe fn simd_saturating_sub<T>(_lhs: T, _rhs: T) -> T;
 /// Starting with the value `y`, add the elements of `x` and accumulate.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_add_ordered<T, U>(_x: T, _y: U) -> U;
+pub unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
 
 /// Adds elements within a vector in arbitrary order. May also be re-associated with
 /// unordered additions on the inputs/outputs.
@@ -390,7 +390,7 @@ pub unsafe fn simd_reduce_add_ordered<T, U>(_x: T, _y: U) -> U;
 /// `U` must be the element type of `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_add_unordered<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_add_unordered<T, U>(x: T) -> U;
 
 /// Multiplies elements within a vector from left to right.
 ///
@@ -401,7 +401,7 @@ pub unsafe fn simd_reduce_add_unordered<T, U>(_x: T) -> U;
 /// Starting with the value `y`, multiply the elements of `x` and accumulate.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_mul_ordered<T, U>(_x: T, _y: U) -> U;
+pub unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
 
 /// Multiplies elements within a vector in arbitrary order. May also be re-associated with
 /// unordered additions on the inputs/outputs.
@@ -411,7 +411,7 @@ pub unsafe fn simd_reduce_mul_ordered<T, U>(_x: T, _y: U) -> U;
 /// `U` must be the element type of `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_mul_unordered<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
 
 /// Checks if all mask values are true.
 ///
@@ -421,7 +421,7 @@ pub unsafe fn simd_reduce_mul_unordered<T, U>(_x: T) -> U;
 /// `x` must contain only `0` or `!0`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_all<T>(_x: T) -> bool;
+pub unsafe fn simd_reduce_all<T>(x: T) -> bool;
 
 /// Checks if any mask value is true.
 ///
@@ -431,7 +431,7 @@ pub unsafe fn simd_reduce_all<T>(_x: T) -> bool;
 /// `x` must contain only `0` or `!0`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_any<T>(_x: T) -> bool;
+pub unsafe fn simd_reduce_any<T>(x: T) -> bool;
 
 /// Returns the maximum element of a vector.
 ///
@@ -442,7 +442,7 @@ pub unsafe fn simd_reduce_any<T>(_x: T) -> bool;
 /// For floating-point values, uses IEEE-754 `maxNum`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_max<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_max<T, U>(x: T) -> U;
 
 /// Returns the minimum element of a vector.
 ///
@@ -453,7 +453,7 @@ pub unsafe fn simd_reduce_max<T, U>(_x: T) -> U;
 /// For floating-point values, uses IEEE-754 `minNum`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_min<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_min<T, U>(x: T) -> U;
 
 /// Logical "ands" all elements together.
 ///
@@ -462,7 +462,7 @@ pub unsafe fn simd_reduce_min<T, U>(_x: T) -> U;
 /// `U` must be the element type of `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_and<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_and<T, U>(x: T) -> U;
 
 /// Logical "ors" all elements together.
 ///
@@ -471,7 +471,7 @@ pub unsafe fn simd_reduce_and<T, U>(_x: T) -> U;
 /// `U` must be the element type of `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_or<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_or<T, U>(x: T) -> U;
 
 /// Logical "exclusive ors" all elements together.
 ///
@@ -480,7 +480,7 @@ pub unsafe fn simd_reduce_or<T, U>(_x: T) -> U;
 /// `U` must be the element type of `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_reduce_xor<T, U>(_x: T) -> U;
+pub unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
 
 /// Truncates an integer vector to a bitmask.
 ///
@@ -517,7 +517,7 @@ pub unsafe fn simd_reduce_xor<T, U>(_x: T) -> U;
 /// `x` must contain only `0` and `!0`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_bitmask<T, U>(_x: T) -> U;
+pub unsafe fn simd_bitmask<T, U>(x: T) -> U;
 
 /// Selects elements from a mask.
 ///
@@ -533,7 +533,7 @@ pub unsafe fn simd_bitmask<T, U>(_x: T) -> U;
 /// `mask` must only contain `0` and `!0`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_select<M, T>(_mask: M, _if_true: T, _if_false: T) -> T;
+pub unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
 
 /// Selects elements from a bitmask.
 ///
@@ -551,7 +551,7 @@ pub unsafe fn simd_select<M, T>(_mask: M, _if_true: T, _if_false: T) -> T;
 /// Padding bits must be all zero.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_select_bitmask<M, T>(_m: M, _yes: T, _no: T) -> T;
+pub unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
 
 /// Calculates the offset from a pointer vector elementwise, potentially
 /// wrapping.
@@ -563,14 +563,14 @@ pub unsafe fn simd_select_bitmask<M, T>(_m: M, _yes: T, _no: T) -> T;
 /// Operates as if by `<ptr>::wrapping_offset`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_arith_offset<T, U>(_ptr: T, _offset: U) -> T;
+pub unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
 
 /// Casts a vector of pointers.
 ///
 /// `T` and `U` must be vectors of pointers with the same number of elements.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_cast_ptr<T, U>(_ptr: T) -> U;
+pub unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
 
 /// Exposes a vector of pointers as a vector of addresses.
 ///
@@ -579,7 +579,7 @@ pub unsafe fn simd_cast_ptr<T, U>(_ptr: T) -> U;
 /// `U` must be a vector of `usize` with the same length as `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_expose_provenance<T, U>(_ptr: T) -> U;
+pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U;
 
 /// Creates a vector of pointers from a vector of addresses.
 ///
@@ -588,56 +588,56 @@ pub unsafe fn simd_expose_provenance<T, U>(_ptr: T) -> U;
 /// `U` must be a vector of pointers, with the same length as `T`.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_with_exposed_provenance<T, U>(_addr: T) -> U;
+pub unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
 
 /// Swaps bytes of each element.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_bswap<T>(_x: T) -> T;
+pub unsafe fn simd_bswap<T>(x: T) -> T;
 
 /// Reverses bits of each element.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_bitreverse<T>(_x: T) -> T;
+pub unsafe fn simd_bitreverse<T>(x: T) -> T;
 
 /// Counts the leading zeros of each element.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_ctlz<T>(_x: T) -> T;
+pub unsafe fn simd_ctlz<T>(x: T) -> T;
 
 /// Counts the number of ones in each element.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_ctpop<T>(_x: T) -> T;
+pub unsafe fn simd_ctpop<T>(x: T) -> T;
 
 /// Counts the trailing zeros of each element.
 ///
 /// `T` must be a vector of integers.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_cttz<T>(_x: T) -> T;
+pub unsafe fn simd_cttz<T>(x: T) -> T;
 
 /// Rounds up each element to the next highest integer-valued float.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_ceil<T>(_x: T) -> T;
+pub unsafe fn simd_ceil<T>(x: T) -> T;
 
 /// Rounds down each element to the next lowest integer-valued float.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_floor<T>(_x: T) -> T;
+pub unsafe fn simd_floor<T>(x: T) -> T;
 
 /// Rounds each element to the closest integer-valued float.
 /// Ties are resolved by rounding away from 0.
@@ -645,7 +645,7 @@ pub unsafe fn simd_floor<T>(_x: T) -> T;
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_round<T>(_x: T) -> T;
+pub unsafe fn simd_round<T>(x: T) -> T;
 
 /// Returns the integer part of each element as an integer-valued float.
 /// In other words, non-integer values are truncated towards zero.
@@ -653,21 +653,21 @@ pub unsafe fn simd_round<T>(_x: T) -> T;
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_trunc<T>(_x: T) -> T;
+pub unsafe fn simd_trunc<T>(x: T) -> T;
 
 /// Takes the square root of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fsqrt<T>(_x: T) -> T;
+pub unsafe fn simd_fsqrt<T>(x: T) -> T;
 
 /// Computes `(x*y) + z` for each element, but without any intermediate rounding.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fma<T>(_x: T, _y: T, _z: T) -> T;
+pub unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
 
 /// Computes `(x*y) + z` for each element, non-deterministically executing either
 /// a fused multiply-add or two operations with rounding of the intermediate result.
@@ -682,53 +682,53 @@ pub unsafe fn simd_fma<T>(_x: T, _y: T, _z: T) -> T;
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_relaxed_fma<T>(_x: T, _y: T, _z: T) -> T;
+pub unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
 
 // Computes the sine of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fsin<T>(_a: T) -> T;
+pub unsafe fn simd_fsin<T>(a: T) -> T;
 
 // Computes the cosine of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fcos<T>(_a: T) -> T;
+pub unsafe fn simd_fcos<T>(a: T) -> T;
 
 // Computes the exponential function of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fexp<T>(_a: T) -> T;
+pub unsafe fn simd_fexp<T>(a: T) -> T;
 
 // Computes 2 raised to the power of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_fexp2<T>(_a: T) -> T;
+pub unsafe fn simd_fexp2<T>(a: T) -> T;
 
 // Computes the base 10 logarithm of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_flog10<T>(_a: T) -> T;
+pub unsafe fn simd_flog10<T>(a: T) -> T;
 
 // Computes the base 2 logarithm of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_flog2<T>(_a: T) -> T;
+pub unsafe fn simd_flog2<T>(a: T) -> T;
 
 // Computes the natural logarithm of each element.
 ///
 /// `T` must be a vector of floats.
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_flog<T>(_a: T) -> T;
+pub unsafe fn simd_flog<T>(a: T) -> T;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 987fa93d598..6e058069756 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -226,7 +226,7 @@ extern crate self as core;
 
 #[prelude_import]
 #[allow(unused)]
-use prelude::rust_2021::*;
+use prelude::rust_2024::*;
 
 #[cfg(not(test))] // See #65860
 #[macro_use]
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index 57f47e66e81..21753d00924 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -8,11 +8,15 @@ use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 /// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
 /// [`SocketAddrV6`]'s respective documentation for more details.
 ///
-/// The size of a `SocketAddr` instance may vary depending on the target operating
-/// system.
-///
 /// [IP address]: IpAddr
 ///
+/// # Portability
+///
+/// `SocketAddr` is intended to be a portable representation of socket addresses and is likely not
+/// the same as the internal socket address type used by the target operating system's API. Like all
+/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon
+/// between builds.
+///
 /// # Examples
 ///
 /// ```
@@ -42,13 +46,16 @@ pub enum SocketAddr {
 ///
 /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
 ///
-/// The size of a `SocketAddrV4` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
 /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
 /// [`IPv4` address]: Ipv4Addr
 ///
+/// # Portability
+///
+/// `SocketAddrV4` is intended to be a portable representation of socket addresses and is likely not
+/// the same as the internal socket address type used by the target operating system's API. Like all
+/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon
+/// between builds.
+///
 /// # Textual representation
 ///
 /// `SocketAddrV4` provides a [`FromStr`](crate::str::FromStr) implementation.
@@ -84,13 +91,16 @@ pub struct SocketAddrV4 {
 ///
 /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
 ///
-/// The size of a `SocketAddrV6` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
 /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
 /// [`IPv6` address]: Ipv6Addr
 ///
+/// # Portability
+///
+/// `SocketAddrV6` is intended to be a portable representation of socket addresses and is likely not
+/// the same as the internal socket address type used by the target operating system's API. Like all
+/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon
+/// between builds.
+///
 /// # Textual representation
 ///
 /// `SocketAddrV6` provides a [`FromStr`](crate::str::FromStr) implementation,
diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml
index a9d1f53761c..6f43ac4809a 100644
--- a/library/panic_abort/Cargo.toml
+++ b/library/panic_abort/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
 description = "Implementation of Rust panics via process aborts"
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = false
diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml
index c2abb79192e..d176434e06b 100644
--- a/library/panic_unwind/Cargo.toml
+++ b/library/panic_unwind/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
 description = "Implementation of Rust panics via stack unwinding"
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = false
diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml
index e54a50aa15c..72cb4e4166f 100644
--- a/library/proc_macro/Cargo.toml
+++ b/library/proc_macro/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "proc_macro"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 [dependencies]
 std = { path = "../std" }
diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml
index 230e8051602..e075a38daea 100644
--- a/library/profiler_builtins/Cargo.toml
+++ b/library/profiler_builtins/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "profiler_builtins"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = false
diff --git a/library/rustc-std-workspace-alloc/Cargo.toml b/library/rustc-std-workspace-alloc/Cargo.toml
index 049ca3e46b5..5a177808d1b 100644
--- a/library/rustc-std-workspace-alloc/Cargo.toml
+++ b/library/rustc-std-workspace-alloc/Cargo.toml
@@ -5,7 +5,7 @@ license = 'MIT OR Apache-2.0'
 description = """
 Hack for the compiler's own build system
 """
-edition = "2021"
+edition = "2024"
 
 [lib]
 path = "lib.rs"
diff --git a/library/rustc-std-workspace-core/Cargo.toml b/library/rustc-std-workspace-core/Cargo.toml
index ff5cfcbd641..9315c08a4d1 100644
--- a/library/rustc-std-workspace-core/Cargo.toml
+++ b/library/rustc-std-workspace-core/Cargo.toml
@@ -5,7 +5,7 @@ license = 'MIT OR Apache-2.0'
 description = """
 Hack for the compiler's own build system
 """
-edition = "2021"
+edition = "2024"
 
 [lib]
 path = "lib.rs"
diff --git a/library/rustc-std-workspace-std/Cargo.toml b/library/rustc-std-workspace-std/Cargo.toml
index 3a1dc2a02b5..f70994e1f88 100644
--- a/library/rustc-std-workspace-std/Cargo.toml
+++ b/library/rustc-std-workspace-std/Cargo.toml
@@ -5,7 +5,7 @@ license = 'MIT OR Apache-2.0'
 description = """
 Hack for the compiler's own build system
 """
-edition = "2021"
+edition = "2024"
 
 [lib]
 path = "lib.rs"
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index f7379c413f1..9d9601b79a7 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.0.0"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
 description = "The Rust Standard Library"
-edition = "2021"
+edition = "2024"
 autobenches = false
 
 [lib]
@@ -35,7 +35,7 @@ miniz_oxide = { version = "0.8.0", optional = true, default-features = false }
 addr2line = { version = "0.24.0", optional = true, default-features = false }
 
 [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
-libc = { version = "0.2.170", default-features = false, features = [
+libc = { version = "0.2.171", default-features = false, features = [
     'rustc-dep-of-std',
 ], public = true }
 
diff --git a/library/std/build.rs b/library/std/build.rs
index cedfd7406a1..a0cfbc4685e 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -42,6 +42,7 @@ fn main() {
         || target_os == "fuchsia"
         || (target_vendor == "fortanix" && target_env == "sgx")
         || target_os == "hermit"
+        || target_os == "trusty"
         || target_os == "l4re"
         || target_os == "redox"
         || target_os == "haiku"
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index ff4a4b35ce4..2487f5a2a50 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -208,20 +208,32 @@ use crate::ops::Index;
 /// # Usage in `const` and `static`
 ///
 /// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed,
-/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the
-/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
-/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this
-/// way is not resistant against HashDoS!**
+/// which means that `HashMap::new` normally cannot be used in a `const` or `static` initializer.
 ///
+/// However, if you need to use a `HashMap` in a `const` or `static` initializer while retaining
+/// random seed generation, you can wrap the `HashMap` in [`LazyLock`].
+///
+/// Alternatively, you can construct a `HashMap` in a `const` or `static` initializer using a different
+/// hasher that does not rely on a random seed. **Be aware that a `HashMap` created this way is not
+/// resistant to HashDoS attacks!**
+///
+/// [`LazyLock`]: crate::sync::LazyLock
 /// ```rust
 /// use std::collections::HashMap;
 /// use std::hash::{BuildHasherDefault, DefaultHasher};
-/// use std::sync::Mutex;
+/// use std::sync::{LazyLock, Mutex};
 ///
-/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> =
+/// // HashMaps with a fixed, non-random hasher
+/// const NONRANDOM_EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> =
 ///     HashMap::with_hasher(BuildHasherDefault::new());
-/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> =
+/// static NONRANDOM_MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> =
 ///     Mutex::new(HashMap::with_hasher(BuildHasherDefault::new()));
+///
+/// // HashMaps using LazyLock to retain random seeding
+/// const RANDOM_EMPTY_MAP: LazyLock<HashMap<String, Vec<i32>>> =
+///     LazyLock::new(HashMap::new);
+/// static RANDOM_MAP: LazyLock<Mutex<HashMap<String, Vec<i32>>>> =
+///     LazyLock::new(|| Mutex::new(HashMap::new()));
 /// ```
 
 #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")]
@@ -1278,69 +1290,6 @@ where
     }
 }
 
-impl<K, V, S> HashMap<K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Creates a raw entry builder for the `HashMap`.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched. After this, insertions into a vacant entry
-    /// still require an owned key to be provided.
-    ///
-    /// Raw entries are useful for such exotic situations as:
-    ///
-    /// * Hash memoization
-    /// * Deferring the creation of an owned key until it is known to be required
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Because raw entries provide much more low-level control, it's much easier
-    /// to put the `HashMap` into an inconsistent state which, while memory-safe,
-    /// will cause the map to produce seemingly random results. Higher-level and
-    /// more foolproof APIs like `entry` should be preferred when possible.
-    ///
-    /// In particular, the hash used to initialize the raw entry must still be
-    /// consistent with the hash of the key that is ultimately stored in the entry.
-    /// This is because implementations of `HashMap` may need to recompute hashes
-    /// when resizing, at which point only the keys are available.
-    ///
-    /// Raw entries give mutable access to the keys. This must not be used
-    /// to modify how the key would compare or hash, as the map will not re-evaluate
-    /// where the key should go, meaning the keys may become "lost" if their
-    /// location does not reflect their state. For instance, if you change a key
-    /// so that the map now contains keys which compare equal, search may start
-    /// acting erratically, with two keys randomly masking each other. Implementations
-    /// are free to assume this doesn't happen (within the limits of memory-safety).
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> {
-        RawEntryBuilderMut { map: self }
-    }
-
-    /// Creates a raw immutable entry builder for the `HashMap`.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched.
-    ///
-    /// This is useful for
-    /// * Hash memoization
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Unless you are in such a situation, higher-level and more foolproof APIs like
-    /// `get` should be preferred.
-    ///
-    /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> {
-        RawEntryBuilder { map: self }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Clone for HashMap<K, V, S>
 where
@@ -1828,404 +1777,6 @@ impl<K, V> Default for IntoValues<K, V> {
     }
 }
 
-/// A builder for computing where in a HashMap a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry_mut`] docs for usage examples.
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This is a lower-level version of [`Entry`].
-///
-/// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`],
-/// then calling one of the methods of that [`RawEntryBuilderMut`].
-///
-/// [`raw_entry_mut`]: HashMap::raw_entry_mut
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
-    /// An occupied entry.
-    Occupied(RawOccupiedEntryMut<'a, K, V, S>),
-    /// A vacant entry.
-    Vacant(RawVacantEntryMut<'a, K, V, S>),
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a, S: 'a> {
-    base: base::RawOccupiedEntryMut<'a, K, V, S>,
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> {
-    base: base::RawVacantEntryMut<'a, K, V, S>,
-}
-
-/// A builder for computing where in a HashMap a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry`] docs for usage examples.
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Creates a `RawEntryMut` from the given key.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        map_raw_entry(self.map.base.raw_entry_mut().from_key(k))
-    }
-
-    /// Creates a `RawEntryMut` from the given key and its hash.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        K: Borrow<Q>,
-        Q: Eq,
-    {
-        map_raw_entry(self.map.base.raw_entry_mut().from_key_hashed_nocheck(hash, k))
-    }
-
-    /// Creates a `RawEntryMut` from the given hash.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
-    where
-        for<'b> F: FnMut(&'b K) -> bool,
-    {
-        map_raw_entry(self.map.base.raw_entry_mut().from_hash(hash, is_match))
-    }
-}
-
-impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Access an entry by key.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.base.raw_entry().from_key(k)
-    }
-
-    /// Access an entry by a key and its hash.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.base.raw_entry().from_key_hashed_nocheck(hash, k)
-    }
-
-    /// Access an entry by hash.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
-    where
-        F: FnMut(&K) -> bool,
-    {
-        self.map.base.raw_entry().from_hash(hash, is_match)
-    }
-}
-
-impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(hash_raw_entry)]
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(hash_raw_entry)]
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| {
-    ///     ("poneyland", "hoho".to_string())
-    /// });
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
-    where
-        F: FnOnce() -> (K, V),
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => {
-                let (k, v) = default();
-                entry.insert(k, v)
-            }
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(hash_raw_entry)]
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 0);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut K, &mut V),
-    {
-        match self {
-            RawEntryMut::Occupied(mut entry) => {
-                {
-                    let (k, v) = entry.get_key_value_mut();
-                    f(k, v);
-                }
-                RawEntryMut::Occupied(entry)
-            }
-            RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry),
-        }
-    }
-}
-
-impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
-    /// Gets a reference to the key in the entry.
-    #[inline]
-    #[must_use]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn key(&self) -> &K {
-        self.base.key()
-    }
-
-    /// Gets a mutable reference to the key in the entry.
-    #[inline]
-    #[must_use]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn key_mut(&mut self) -> &mut K {
-        self.base.key_mut()
-    }
-
-    /// Converts the entry into a mutable reference to the key in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn into_key(self) -> &'a mut K {
-        self.base.into_key()
-    }
-
-    /// Gets a reference to the value in the entry.
-    #[inline]
-    #[must_use]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn get(&self) -> &V {
-        self.base.get()
-    }
-
-    /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn into_mut(self) -> &'a mut V {
-        self.base.into_mut()
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    #[inline]
-    #[must_use]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn get_mut(&mut self) -> &mut V {
-        self.base.get_mut()
-    }
-
-    /// Gets a reference to the key and value in the entry.
-    #[inline]
-    #[must_use]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn get_key_value(&mut self) -> (&K, &V) {
-        self.base.get_key_value()
-    }
-
-    /// Gets a mutable reference to the key and value in the entry.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
-        self.base.get_key_value_mut()
-    }
-
-    /// Converts the `OccupiedEntry` into a mutable reference to the key and value in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
-        self.base.into_key_value()
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn insert(&mut self, value: V) -> V {
-        self.base.insert(value)
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn insert_key(&mut self, key: K) -> K {
-        self.base.insert_key(key)
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn remove(self) -> V {
-        self.base.remove()
-    }
-
-    /// Take the ownership of the key and value from the map.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn remove_entry(self) -> (K, V) {
-        self.base.remove_entry()
-    }
-}
-
-impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
-    /// Sets the value of the entry with the `VacantEntry`'s key,
-    /// and returns a mutable reference to it.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        self.base.insert(key, value)
-    }
-
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    #[inline]
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        self.base.insert_hashed_nocheck(hash, key, value)
-    }
-}
-
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K, V, S> Debug for RawEntryBuilderMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
-            RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(),
-        }
-    }
-}
-
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K: Debug, V: Debug, S> Debug for RawOccupiedEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawOccupiedEntryMut")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K, V, S> Debug for RawVacantEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawVacantEntryMut").finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish_non_exhaustive()
-    }
-}
-
 /// A view into a single entry in a map, which may either be vacant or occupied.
 ///
 /// This `enum` is constructed from the [`entry`] method on [`HashMap`].
@@ -3298,16 +2849,6 @@ pub(super) fn map_try_reserve_error(err: hashbrown::TryReserveError) -> TryReser
     }
 }
 
-#[inline]
-fn map_raw_entry<'a, K: 'a, V: 'a, S: 'a>(
-    raw: base::RawEntryMut<'a, K, V, S>,
-) -> RawEntryMut<'a, K, V, S> {
-    match raw {
-        base::RawEntryMut::Occupied(base) => RawEntryMut::Occupied(RawOccupiedEntryMut { base }),
-        base::RawEntryMut::Vacant(base) => RawEntryMut::Vacant(RawVacantEntryMut { base }),
-    }
-}
-
 #[allow(dead_code)]
 fn assert_covariance() {
     fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> {
diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index a275488a556..9f7df20a1d7 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -852,99 +852,6 @@ fn test_try_reserve() {
     }
 }
 
-#[test]
-fn test_raw_entry() {
-    use super::RawEntryMut::{Occupied, Vacant};
-
-    let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-    let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-    let compute_hash = |map: &HashMap<i32, i32>, k: i32| -> u64 {
-        use core::hash::{BuildHasher, Hash, Hasher};
-
-        let mut hasher = map.hasher().build_hasher();
-        k.hash(&mut hasher);
-        hasher.finish()
-    };
-
-    // Existing key (insert)
-    match map.raw_entry_mut().from_key(&1) {
-        Vacant(_) => unreachable!(),
-        Occupied(mut view) => {
-            assert_eq!(view.get(), &10);
-            assert_eq!(view.insert(100), 10);
-        }
-    }
-    let hash1 = compute_hash(&map, 1);
-    assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100));
-    assert_eq!(map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(), (&1, &100));
-    assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(), (&1, &100));
-    assert_eq!(map.len(), 6);
-
-    // Existing key (update)
-    match map.raw_entry_mut().from_key(&2) {
-        Vacant(_) => unreachable!(),
-        Occupied(mut view) => {
-            let v = view.get_mut();
-            let new_v = (*v) * 10;
-            *v = new_v;
-        }
-    }
-    let hash2 = compute_hash(&map, 2);
-    assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200));
-    assert_eq!(map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(), (&2, &200));
-    assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(), (&2, &200));
-    assert_eq!(map.len(), 6);
-
-    // Existing key (take)
-    let hash3 = compute_hash(&map, 3);
-    match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) {
-        Vacant(_) => unreachable!(),
-        Occupied(view) => {
-            assert_eq!(view.remove_entry(), (3, 30));
-        }
-    }
-    assert_eq!(map.raw_entry().from_key(&3), None);
-    assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None);
-    assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None);
-    assert_eq!(map.len(), 5);
-
-    // Nonexistent key (insert)
-    match map.raw_entry_mut().from_key(&10) {
-        Occupied(_) => unreachable!(),
-        Vacant(view) => {
-            assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000));
-        }
-    }
-    assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000));
-    assert_eq!(map.len(), 6);
-
-    // Ensure all lookup methods produce equivalent results.
-    for k in 0..12 {
-        let hash = compute_hash(&map, k);
-        let v = map.get(&k).cloned();
-        let kv = v.as_ref().map(|v| (&k, v));
-
-        assert_eq!(map.raw_entry().from_key(&k), kv);
-        assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv);
-        assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
-
-        match map.raw_entry_mut().from_key(&k) {
-            Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-            Vacant(_) => assert_eq!(v, None),
-        }
-        match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) {
-            Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-            Vacant(_) => assert_eq!(v, None),
-        }
-        match map.raw_entry_mut().from_hash(hash, |q| *q == k) {
-            Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-            Vacant(_) => assert_eq!(v, None),
-        }
-    }
-}
-
 mod test_extract_if {
     use super::*;
     use crate::panic::{AssertUnwindSafe, catch_unwind};
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 46b5860123f..f9a360585e8 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -14,7 +14,8 @@
         target_os = "emscripten",
         target_os = "wasi",
         target_env = "sgx",
-        target_os = "xous"
+        target_os = "xous",
+        target_os = "trusty",
     ))
 ))]
 mod tests;
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 5aa048c4cbc..8472f903050 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -373,8 +373,8 @@ pub enum ErrorKind {
     TooManyLinks,
     /// A filename was invalid.
     ///
-    /// This error can also cause if it exceeded the filename length limit.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    /// This error can also occur if a length limit for a name was exceeded.
+    #[stable(feature = "io_error_invalid_filename", since = "CURRENT_RUSTC_VERSION")]
     InvalidFilename,
     /// Program argument list too long.
     ///
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index f64f034cce7..fd962b0415c 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -811,13 +811,17 @@ fn read_to_end_error() {
 }
 
 #[test]
-// Miri does not support signalling OOM
-#[cfg_attr(miri, ignore)]
-// 64-bit only to be sure the allocator will fail fast on an impossible to satisfy size
-#[cfg(target_pointer_width = "64")]
 fn try_oom_error() {
-    let mut v = Vec::<u8>::new();
-    let reserve_err = v.try_reserve(isize::MAX as usize - 1).unwrap_err();
+    use alloc::alloc::Layout;
+    use alloc::collections::{TryReserveError, TryReserveErrorKind};
+
+    // We simulate a `Vec::try_reserve` error rather than attempting a huge size for real. This way
+    // we're not subject to the whims of optimization that might skip the actual allocation, and it
+    // also works for 32-bit targets and miri that might not OOM at all.
+    let layout = Layout::new::<u8>();
+    let kind = TryReserveErrorKind::AllocError { layout, non_exhaustive: () };
+    let reserve_err = TryReserveError::from(kind);
+
     let io_err = io::Error::from(reserve_err);
     assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind());
 }
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 5ac3dbc3e98..c07c391892d 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -1064,7 +1064,7 @@ mod move_keyword {}
 /// ```rust,compile_fail,E0502
 /// let mut v = vec![0, 1];
 /// let mut_ref_v = &mut v;
-/// ##[allow(unused)]
+/// # #[allow(unused)]
 /// let ref_v = &v;
 /// mut_ref_v.push(2);
 /// ```
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 9b68f872955..6a951426407 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -5,7 +5,8 @@
     not(any(
         target_os = "emscripten",
         all(target_os = "wasi", target_env = "p1"),
-        target_os = "xous"
+        target_os = "xous",
+        target_os = "trusty",
     ))
 ))]
 mod tests;
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 3eb798ad34a..a97b3299774 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -4,7 +4,8 @@
         target_os = "emscripten",
         all(target_os = "wasi", target_env = "p1"),
         target_env = "sgx",
-        target_os = "xous"
+        target_os = "xous",
+        target_os = "trusty",
     ))
 ))]
 mod tests;
diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs
index 35de4860fe2..95cf4932e6e 100644
--- a/library/std/src/os/fd/mod.rs
+++ b/library/std/src/os/fd/mod.rs
@@ -13,6 +13,7 @@ mod raw;
 mod owned;
 
 // Implementations for `AsRawFd` etc. for network types.
+#[cfg(not(target_os = "trusty"))]
 mod net;
 
 #[cfg(test)]
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 5cec11ecccf..701cf823357 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -4,12 +4,20 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
 use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+#[cfg(not(target_os = "trusty"))]
+use crate::fs;
 use crate::marker::PhantomData;
 use crate::mem::ManuallyDrop;
-#[cfg(not(any(target_arch = "wasm32", target_env = "sgx", target_os = "hermit")))]
+#[cfg(not(any(
+    target_arch = "wasm32",
+    target_env = "sgx",
+    target_os = "hermit",
+    target_os = "trusty"
+)))]
 use crate::sys::cvt;
+#[cfg(not(target_os = "trusty"))]
 use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::{fmt, fs, io};
+use crate::{fmt, io};
 
 type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
 
@@ -87,7 +95,7 @@ impl OwnedFd {
 impl BorrowedFd<'_> {
     /// Creates a new `OwnedFd` instance that shares the same underlying file
     /// description as the existing `BorrowedFd` instance.
-    #[cfg(not(any(target_arch = "wasm32", target_os = "hermit")))]
+    #[cfg(not(any(target_arch = "wasm32", target_os = "hermit", target_os = "trusty")))]
     #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
         // We want to atomically duplicate this file descriptor and set the
@@ -110,7 +118,7 @@ impl BorrowedFd<'_> {
 
     /// Creates a new `OwnedFd` instance that shares the same underlying file
     /// description as the existing `BorrowedFd` instance.
-    #[cfg(any(target_arch = "wasm32", target_os = "hermit"))]
+    #[cfg(any(target_arch = "wasm32", target_os = "hermit", target_os = "trusty"))]
     #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
         Err(crate::io::Error::UNSUPPORTED_PLATFORM)
@@ -280,6 +288,7 @@ impl AsFd for OwnedFd {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for fs::File {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -288,6 +297,7 @@ impl AsFd for fs::File {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<fs::File> for OwnedFd {
     /// Takes ownership of a [`File`](fs::File)'s underlying file descriptor.
     #[inline]
@@ -297,6 +307,7 @@ impl From<fs::File> for OwnedFd {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for fs::File {
     /// Returns a [`File`](fs::File) that takes ownership of the given
     /// file descriptor.
@@ -307,6 +318,7 @@ impl From<OwnedFd> for fs::File {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for crate::net::TcpStream {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -315,6 +327,7 @@ impl AsFd for crate::net::TcpStream {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<crate::net::TcpStream> for OwnedFd {
     /// Takes ownership of a [`TcpStream`](crate::net::TcpStream)'s socket file descriptor.
     #[inline]
@@ -324,6 +337,7 @@ impl From<crate::net::TcpStream> for OwnedFd {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for crate::net::TcpStream {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
@@ -334,6 +348,7 @@ impl From<OwnedFd> for crate::net::TcpStream {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for crate::net::TcpListener {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -342,6 +357,7 @@ impl AsFd for crate::net::TcpListener {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<crate::net::TcpListener> for OwnedFd {
     /// Takes ownership of a [`TcpListener`](crate::net::TcpListener)'s socket file descriptor.
     #[inline]
@@ -351,6 +367,7 @@ impl From<crate::net::TcpListener> for OwnedFd {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for crate::net::TcpListener {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
@@ -361,6 +378,7 @@ impl From<OwnedFd> for crate::net::TcpListener {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for crate::net::UdpSocket {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -369,6 +387,7 @@ impl AsFd for crate::net::UdpSocket {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<crate::net::UdpSocket> for OwnedFd {
     /// Takes ownership of a [`UdpSocket`](crate::net::UdpSocket)'s file descriptor.
     #[inline]
@@ -378,6 +397,7 @@ impl From<crate::net::UdpSocket> for OwnedFd {
 }
 
 #[stable(feature = "io_safety", since = "1.63.0")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for crate::net::UdpSocket {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 03dff94350d..083ac6e3fe6 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -5,6 +5,9 @@
 #[cfg(target_os = "hermit")]
 use hermit_abi as libc;
 
+#[cfg(not(target_os = "trusty"))]
+use crate::fs;
+use crate::io;
 #[cfg(target_os = "hermit")]
 use crate::os::hermit::io::OwnedFd;
 #[cfg(not(target_os = "hermit"))]
@@ -15,8 +18,8 @@ use crate::os::unix::io::AsFd;
 use crate::os::unix::io::OwnedFd;
 #[cfg(target_os = "wasi")]
 use crate::os::wasi::io::OwnedFd;
+#[cfg(not(target_os = "trusty"))]
 use crate::sys_common::{AsInner, IntoInner};
-use crate::{fs, io};
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -161,6 +164,7 @@ impl FromRawFd for RawFd {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsRawFd for fs::File {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
@@ -168,6 +172,7 @@ impl AsRawFd for fs::File {
     }
 }
 #[stable(feature = "from_raw_os", since = "1.1.0")]
+#[cfg(not(target_os = "trusty"))]
 impl FromRawFd for fs::File {
     #[inline]
     unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
@@ -175,6 +180,7 @@ impl FromRawFd for fs::File {
     }
 }
 #[stable(feature = "into_raw_os", since = "1.4.0")]
+#[cfg(not(target_os = "trusty"))]
 impl IntoRawFd for fs::File {
     #[inline]
     fn into_raw_fd(self) -> RawFd {
@@ -183,6 +189,7 @@ impl IntoRawFd for fs::File {
 }
 
 #[stable(feature = "asraw_stdio", since = "1.21.0")]
+#[cfg(not(target_os = "trusty"))]
 impl AsRawFd for io::Stdin {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
@@ -207,6 +214,7 @@ impl AsRawFd for io::Stderr {
 }
 
 #[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+#[cfg(not(target_os = "trusty"))]
 impl<'a> AsRawFd for io::StdinLock<'a> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index e28a1c3e6d5..58cbecd30e5 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -169,6 +169,8 @@ pub mod rtems;
 pub mod solaris;
 #[cfg(target_os = "solid_asp3")]
 pub mod solid;
+#[cfg(target_os = "trusty")]
+pub mod trusty;
 #[cfg(target_os = "uefi")]
 pub mod uefi;
 #[cfg(target_os = "vita")]
@@ -178,7 +180,7 @@ pub mod vxworks;
 #[cfg(target_os = "xous")]
 pub mod xous;
 
-#[cfg(any(unix, target_os = "hermit", target_os = "wasi", doc))]
+#[cfg(any(unix, target_os = "hermit", target_os = "trusty", target_os = "wasi", doc))]
 pub mod fd;
 
 #[cfg(any(target_os = "linux", target_os = "android", doc))]
diff --git a/library/std/src/os/trusty/io/mod.rs b/library/std/src/os/trusty/io/mod.rs
new file mode 100644
index 00000000000..4cfd448305b
--- /dev/null
+++ b/library/std/src/os/trusty/io/mod.rs
@@ -0,0 +1,4 @@
+#![stable(feature = "os_fd", since = "1.66.0")]
+
+#[stable(feature = "os_fd", since = "1.66.0")]
+pub use crate::os::fd::*;
diff --git a/library/std/src/os/trusty/mod.rs b/library/std/src/os/trusty/mod.rs
new file mode 100644
index 00000000000..cc67c92d7ff
--- /dev/null
+++ b/library/std/src/os/trusty/mod.rs
@@ -0,0 +1,3 @@
+#![stable(feature = "rust1", since = "1.0.0")]
+
+pub mod io;
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 04a45fd035a..0427feb2955 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -276,63 +276,89 @@ impl FileExt for fs::File {
 }
 
 /// Unix-specific extensions to [`fs::Permissions`].
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::fs::{File, Permissions};
+/// use std::io::{ErrorKind, Result as IoResult};
+/// use std::os::unix::fs::PermissionsExt;
+///
+/// fn main() -> IoResult<()> {
+///     let name = "test_file_for_permissions";
+///
+///     // make sure file does not exist
+///     let _ = std::fs::remove_file(name);
+///     assert_eq!(
+///         File::open(name).unwrap_err().kind(),
+///         ErrorKind::NotFound,
+///         "file already exists"
+///     );
+///
+///     // full read/write/execute mode bits for owner of file
+///     // that we want to add to existing mode bits
+///     let my_mode = 0o700;
+///
+///     // create new file with specified permissions
+///     {
+///         let file = File::create(name)?;
+///         let mut permissions = file.metadata()?.permissions();
+///         eprintln!("Current permissions: {:o}", permissions.mode());
+///
+///         // make sure new permissions are not already set
+///         assert!(
+///             permissions.mode() & my_mode != my_mode,
+///             "permissions already set"
+///         );
+///
+///         // either use `set_mode` to change an existing Permissions struct
+///         permissions.set_mode(permissions.mode() | my_mode);
+///
+///         // or use `from_mode` to construct a new Permissions struct
+///         permissions = Permissions::from_mode(permissions.mode() | my_mode);
+///
+///         // write new permissions to file
+///         file.set_permissions(permissions)?;
+///     }
+///
+///     let permissions = File::open(name)?.metadata()?.permissions();
+///     eprintln!("New permissions: {:o}", permissions.mode());
+///
+///     // assert new permissions were set
+///     assert_eq!(
+///         permissions.mode() & my_mode,
+///         my_mode,
+///         "new permissions not set"
+///     );
+///     Ok(())
+/// }
+/// ```
+///
+/// ```no_run
+/// use std::fs::Permissions;
+/// use std::os::unix::fs::PermissionsExt;
+///
+/// // read/write for owner and read for others
+/// let my_mode = 0o644;
+/// let mut permissions = Permissions::from_mode(my_mode);
+/// assert_eq!(permissions.mode(), my_mode);
+///
+/// // read/write/execute for owner
+/// let other_mode = 0o700;
+/// permissions.set_mode(other_mode);
+/// assert_eq!(permissions.mode(), other_mode);
+/// ```
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
-    /// Returns the underlying raw `st_mode` bits that contain the standard
-    /// Unix permissions for this file.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::os::unix::fs::PermissionsExt;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::create("foo.txt")?;
-    ///     let metadata = f.metadata()?;
-    ///     let permissions = metadata.permissions();
-    ///
-    ///     println!("permissions: {:o}", permissions.mode());
-    ///     Ok(())
-    /// }
-    /// ```
+    /// Returns the mode permission bits
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
 
-    /// Sets the underlying raw bits for this set of permissions.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::os::unix::fs::PermissionsExt;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::create("foo.txt")?;
-    ///     let metadata = f.metadata()?;
-    ///     let mut permissions = metadata.permissions();
-    ///
-    ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
-    ///     assert_eq!(permissions.mode(), 0o644);
-    ///     Ok(())
-    /// }
-    /// ```
+    /// Sets the mode permission bits.
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn set_mode(&mut self, mode: u32);
 
-    /// Creates a new instance of `Permissions` from the given set of Unix
-    /// permission bits.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fs::Permissions;
-    /// use std::os::unix::fs::PermissionsExt;
-    ///
-    /// // Read/write for owner and read for others.
-    /// let permissions = Permissions::from_mode(0o644);
-    /// assert_eq!(permissions.mode(), 0o644);
-    /// ```
+    /// Creates a new instance from the given mode permission bits.
     #[stable(feature = "fs_ext", since = "1.1.0")]
     #[cfg_attr(not(test), rustc_diagnostic_item = "permissions_from_mode")]
     fn from_mode(mode: u32) -> Self;
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index fa65a7c51bf..a084f452e55 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -531,7 +531,7 @@ impl<'a> ProcThreadAttributeListBuilder<'a> {
     ///     pub Y: i16,
     /// }
     ///
-    /// extern "system" {
+    /// unsafe extern "system" {
     ///     fn CreatePipe(
     ///         hreadpipe: *mut HANDLE,
     ///         hwritepipe: *mut HANDLE,
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index bdd4844b651..37762c65f65 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -154,7 +154,8 @@
         target_os = "emscripten",
         target_os = "wasi",
         target_env = "sgx",
-        target_os = "xous"
+        target_os = "xous",
+        target_os = "trusty",
     ))
 ))]
 mod tests;
diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs
index 2c0b533a570..8489e17c971 100644
--- a/library/std/src/sys/alloc/mod.rs
+++ b/library/std/src/sys/alloc/mod.rs
@@ -72,6 +72,7 @@ cfg_if::cfg_if! {
         target_family = "unix",
         target_os = "wasi",
         target_os = "teeos",
+        target_os = "trusty",
     ))] {
         mod unix;
     } else if #[cfg(target_os = "windows")] {
diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs
index 45e93deffa3..56aed7dfd8e 100644
--- a/library/std/src/sys/fs/uefi.rs
+++ b/library/std/src/sys/fs/uefi.rs
@@ -1,14 +1,21 @@
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::hash::{Hash, Hasher};
+use crate::hash::Hash;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
 
+#[expect(dead_code)]
+const FILE_PERMISSIONS_MASK: u64 = r_efi::protocols::file::READ_ONLY;
+
 pub struct File(!);
 
-pub struct FileAttr(!);
+#[derive(Clone)]
+pub struct FileAttr {
+    attr: u64,
+    size: u64,
+}
 
 pub struct ReadDir(!);
 
@@ -20,42 +27,40 @@ pub struct OpenOptions {}
 #[derive(Copy, Clone, Debug, Default)]
 pub struct FileTimes {}
 
-pub struct FilePermissions(!);
+#[derive(Clone, PartialEq, Eq, Debug)]
+// Bool indicates if file is readonly
+pub struct FilePermissions(bool);
 
-pub struct FileType(!);
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+// Bool indicates if directory
+pub struct FileType(bool);
 
 #[derive(Debug)]
 pub struct DirBuilder {}
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
-        self.0
+        self.size
     }
 
     pub fn perm(&self) -> FilePermissions {
-        self.0
+        FilePermissions::from_attr(self.attr)
     }
 
     pub fn file_type(&self) -> FileType {
-        self.0
+        FileType::from_attr(self.attr)
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        self.0
+        unsupported()
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        self.0
+        unsupported()
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        self.0
-    }
-}
-
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        self.0
+        unsupported()
     }
 }
 
@@ -64,28 +69,17 @@ impl FilePermissions {
         self.0
     }
 
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        self.0
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.0 = readonly
     }
-}
 
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        self.0
+    const fn from_attr(attr: u64) -> Self {
+        Self(attr & r_efi::protocols::file::READ_ONLY != 0)
     }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        self.0
-    }
-}
 
-impl Eq for FilePermissions {}
-
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    #[expect(dead_code)]
+    const fn to_attr(&self) -> u64 {
+        if self.0 { r_efi::protocols::file::READ_ONLY } else { 0 }
     }
 }
 
@@ -100,39 +94,16 @@ impl FileType {
     }
 
     pub fn is_file(&self) -> bool {
-        self.0
+        !self.is_dir()
     }
 
+    // Symlinks are not supported in UEFI
     pub fn is_symlink(&self) -> bool {
-        self.0
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        self.0
+        false
     }
-}
-
-impl Copy for FileType {}
 
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        self.0
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        self.0
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    const fn from_attr(attr: u64) -> Self {
+        Self(attr & r_efi::protocols::file::DIRECTORY != 0)
     }
 }
 
@@ -303,8 +274,8 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    unsupported()
 }
 
 pub fn rmdir(_p: &Path) -> io::Result<()> {
diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs
index 9be018c8a53..fbefc62ac88 100644
--- a/library/std/src/sys/pal/mod.rs
+++ b/library/std/src/sys/pal/mod.rs
@@ -37,6 +37,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "hermit")] {
         mod hermit;
         pub use self::hermit::*;
+    } else if #[cfg(target_os = "trusty")] {
+        mod trusty;
+        pub use self::trusty::*;
     } else if #[cfg(all(target_os = "wasi", target_env = "p2"))] {
         mod wasip2;
         pub use self::wasip2::*;
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
index 301e3299c05..3fe6dee3d6f 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
@@ -6,7 +6,7 @@ use super::super::mem::{is_enclave_range, is_user_range};
 use crate::arch::asm;
 use crate::cell::UnsafeCell;
 use crate::convert::TryInto;
-use crate::mem::{self, ManuallyDrop};
+use crate::mem::{self, ManuallyDrop, MaybeUninit};
 use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
 use crate::pin::PinCoerceUnsized;
 use crate::ptr::{self, NonNull};
@@ -209,6 +209,45 @@ impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
     }
 }
 
+/// A type which can a destination for safely copying from userspace.
+///
+/// # Safety
+///
+/// Requires that `T` and `Self` have identical layouts.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub unsafe trait UserSafeCopyDestination<T: ?Sized> {
+    /// Returns a pointer for writing to the value.
+    fn as_mut_ptr(&mut self) -> *mut T;
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+unsafe impl<T> UserSafeCopyDestination<T> for T {
+    fn as_mut_ptr(&mut self) -> *mut T {
+        self as _
+    }
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+unsafe impl<T> UserSafeCopyDestination<[T]> for [T] {
+    fn as_mut_ptr(&mut self) -> *mut [T] {
+        self as _
+    }
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+unsafe impl<T> UserSafeCopyDestination<T> for MaybeUninit<T> {
+    fn as_mut_ptr(&mut self) -> *mut T {
+        self as *mut Self as _
+    }
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+unsafe impl<T> UserSafeCopyDestination<[T]> for [MaybeUninit<T>] {
+    fn as_mut_ptr(&mut self) -> *mut [T] {
+        self as *mut Self as _
+    }
+}
+
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: ?Sized> User<T>
 where
@@ -544,12 +583,12 @@ where
     /// # Panics
     /// This function panics if the destination doesn't have the same size as
     /// the source. This can happen for dynamically-sized types such as slices.
-    pub fn copy_to_enclave(&self, dest: &mut T) {
+    pub fn copy_to_enclave<U: ?Sized + UserSafeCopyDestination<T>>(&self, dest: &mut U) {
         unsafe {
             assert_eq!(size_of_val(dest), size_of_val(&*self.0.get()));
             copy_from_userspace(
                 self.0.get() as *const T as *const u8,
-                dest as *mut T as *mut u8,
+                dest.as_mut_ptr() as *mut u8,
                 size_of_val(dest),
             );
         }
@@ -639,25 +678,18 @@ where
         unsafe { (*self.0.get()).len() }
     }
 
-    /// Copies the value from user memory and place it into `dest`. Afterwards,
-    /// `dest` will contain exactly `self.len()` elements.
-    ///
-    /// # Panics
-    /// This function panics if the destination doesn't have the same size as
-    /// the source. This can happen for dynamically-sized types such as slices.
-    pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
-        if let Some(missing) = self.len().checked_sub(dest.capacity()) {
-            dest.reserve(missing)
-        }
+    /// Copies the value from user memory and appends it to `dest`.
+    pub fn append_to_enclave_vec(&self, dest: &mut Vec<T>) {
+        dest.reserve(self.len());
+        self.copy_to_enclave(&mut dest.spare_capacity_mut()[..self.len()]);
         // SAFETY: We reserve enough space above.
-        unsafe { dest.set_len(self.len()) };
-        self.copy_to_enclave(&mut dest[..]);
+        unsafe { dest.set_len(dest.len() + self.len()) };
     }
 
     /// Copies the value from user memory into a vector in enclave memory.
     pub fn to_enclave(&self) -> Vec<T> {
         let mut ret = Vec::with_capacity(self.len());
-        self.copy_to_enclave_vec(&mut ret);
+        self.append_to_enclave_vec(&mut ret);
         ret
     }
 
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
index 90b9b59471a..cbdaf439b28 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
@@ -1,5 +1,7 @@
 use crate::cmp;
-use crate::io::{Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult};
+use crate::io::{
+    BorrowedCursor, Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult,
+};
 use crate::random::{DefaultRandomSource, Random};
 use crate::time::{Duration, Instant};
 
@@ -36,6 +38,19 @@ pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
     }
 }
 
+/// Usercall `read` with an uninitialized buffer. See the ABI documentation for
+/// more information.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub fn read_buf(fd: Fd, mut buf: BorrowedCursor<'_>) -> IoResult<()> {
+    unsafe {
+        let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.capacity());
+        let len = raw::read(fd, userbuf.as_mut_ptr().cast(), userbuf.len()).from_sgx_result()?;
+        userbuf[..len].copy_to_enclave(&mut buf.as_mut()[..len]);
+        buf.advance_unchecked(len);
+        Ok(())
+    }
+}
+
 /// Usercall `read_alloc`. See the ABI documentation for more information.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
diff --git a/library/std/src/sys/pal/sgx/fd.rs b/library/std/src/sys/pal/sgx/fd.rs
index 3bb3189a1d1..399f6a16489 100644
--- a/library/std/src/sys/pal/sgx/fd.rs
+++ b/library/std/src/sys/pal/sgx/fd.rs
@@ -29,7 +29,7 @@ impl FileDesc {
     }
 
     pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
-        crate::io::default_read_buf(|b| self.read(b), buf)
+        usercalls::read_buf(self.fd, buf)
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
new file mode 100644
index 00000000000..7034b643d8e
--- /dev/null
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -0,0 +1,21 @@
+//! System bindings for the Trusty OS.
+
+#[path = "../unsupported/args.rs"]
+pub mod args;
+#[path = "../unsupported/common.rs"]
+#[deny(unsafe_op_in_unsafe_fn)]
+mod common;
+#[path = "../unsupported/env.rs"]
+pub mod env;
+#[path = "../unsupported/os.rs"]
+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"]
+pub mod time;
+
+pub use common::*;
diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs
index f42351deb92..870039602bc 100644
--- a/library/std/src/sys/random/mod.rs
+++ b/library/std/src/sys/random/mod.rs
@@ -60,6 +60,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "teeos")] {
         mod teeos;
         pub use teeos::fill_bytes;
+    } else if #[cfg(target_os = "trusty")] {
+        mod trusty;
+        pub use trusty::fill_bytes;
     } else if #[cfg(target_os = "uefi")] {
         mod uefi;
         pub use uefi::fill_bytes;
diff --git a/library/std/src/sys/random/trusty.rs b/library/std/src/sys/random/trusty.rs
new file mode 100644
index 00000000000..da6ca3eea24
--- /dev/null
+++ b/library/std/src/sys/random/trusty.rs
@@ -0,0 +1,7 @@
+extern "C" {
+    fn trusty_rng_secure_rand(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t);
+}
+
+pub fn fill_bytes(bytes: &mut [u8]) {
+    unsafe { trusty_rng_secure_rand(bytes.as_mut_ptr().cast(), bytes.len()) }
+}
diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs
index 2a9167bfe96..336d4c8527d 100644
--- a/library/std/src/sys/stdio/mod.rs
+++ b/library/std/src/sys/stdio/mod.rs
@@ -19,6 +19,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "teeos")] {
         mod teeos;
         pub use teeos::*;
+    } else if #[cfg(target_os = "trusty")] {
+        mod trusty;
+        pub use trusty::*;
     } else if #[cfg(target_os = "uefi")] {
         mod uefi;
         pub use uefi::*;
diff --git a/library/std/src/sys/stdio/sgx.rs b/library/std/src/sys/stdio/sgx.rs
index 03d754cb217..1894c098d18 100644
--- a/library/std/src/sys/stdio/sgx.rs
+++ b/library/std/src/sys/stdio/sgx.rs
@@ -1,6 +1,6 @@
 use fortanix_sgx_abi as abi;
 
-use crate::io;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::sys::fd::FileDesc;
 
 pub struct Stdin(());
@@ -24,6 +24,19 @@ impl io::Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         with_std_fd(abi::FD_STDIN, |fd| fd.read(buf))
     }
+
+    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
+        with_std_fd(abi::FD_STDIN, |fd| fd.read_buf(buf))
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDIN, |fd| fd.read_vectored(bufs))
+    }
+
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        true
+    }
 }
 
 impl Stdout {
@@ -40,6 +53,15 @@ impl io::Write for Stdout {
     fn flush(&mut self) -> io::Result<()> {
         with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
     }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDOUT, |fd| fd.write_vectored(bufs))
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
 }
 
 impl Stderr {
@@ -56,6 +78,15 @@ impl io::Write for Stderr {
     fn flush(&mut self) -> io::Result<()> {
         with_std_fd(abi::FD_STDERR, |fd| fd.flush())
     }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDERR, |fd| fd.write_vectored(bufs))
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
 }
 
 pub const STDIN_BUF_SIZE: usize = crate::sys::io::DEFAULT_BUF_SIZE;
diff --git a/library/std/src/sys/stdio/trusty.rs b/library/std/src/sys/stdio/trusty.rs
new file mode 100644
index 00000000000..d393e95394d
--- /dev/null
+++ b/library/std/src/sys/stdio/trusty.rs
@@ -0,0 +1,81 @@
+use crate::io;
+
+pub struct Stdin;
+pub struct Stdout;
+pub struct Stderr;
+
+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
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        _write(libc::STDOUT_FILENO, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub const fn new() -> Stderr {
+        Stderr
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        _write(libc::STDERR_FILENO, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+pub const STDIN_BUF_SIZE: usize = 0;
+
+pub fn is_ebadf(_err: &io::Error) -> bool {
+    true
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Some(Stderr)
+}
+
+fn _write(fd: i32, message: &[u8]) -> io::Result<usize> {
+    let mut iov = libc::iovec { iov_base: message.as_ptr() as *mut _, iov_len: message.len() };
+    loop {
+        // SAFETY: syscall, safe arguments.
+        let ret = unsafe { libc::writev(fd, &iov, 1) };
+        if ret < 0 {
+            return Err(io::Error::last_os_error());
+        }
+        let ret = ret as usize;
+        if ret > iov.iov_len {
+            return Err(io::Error::last_os_error());
+        }
+        if ret == iov.iov_len {
+            return Ok(message.len());
+        }
+        // SAFETY: ret has been checked to be less than the length of
+        // the buffer
+        iov.iov_base = unsafe { iov.iov_base.add(ret) };
+        iov.iov_len -= ret;
+    }
+}
diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs
index f0a13323ec9..1ff13154b7b 100644
--- a/library/std/src/sys/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
@@ -28,6 +28,7 @@ cfg_if::cfg_if! {
         all(target_family = "wasm", not(target_feature = "atomics")),
         target_os = "uefi",
         target_os = "zkvm",
+        target_os = "trusty",
     ))] {
         mod statik;
         pub use statik::{EagerStorage, LazyStorage, thread_local_inner};
@@ -91,6 +92,7 @@ pub(crate) mod guard {
             )),
             target_os = "uefi",
             target_os = "zkvm",
+            target_os = "trusty",
         ))] {
             pub(crate) fn enable() {
                 // FIXME: Right now there is no concept of "thread exit" on
diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs
index 5180f3d40f3..19389a9178e 100644
--- a/library/std/tests/floats/f16.rs
+++ b/library/std/tests/floats/f16.rs
@@ -461,18 +461,16 @@ fn test_recip() {
 #[test]
 #[cfg(reliable_f16_math)]
 fn test_powi() {
-    // FIXME(llvm19): LLVM misoptimizes `powi.f16`
-    // <https://github.com/llvm/llvm-project/issues/98665>
-    // let nan: f16 = f16::NAN;
-    // let inf: f16 = f16::INFINITY;
-    // let neg_inf: f16 = f16::NEG_INFINITY;
-    // assert_eq!(1.0f16.powi(1), 1.0);
-    // assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
-    // assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
-    // assert_eq!(8.3f16.powi(0), 1.0);
-    // assert!(nan.powi(2).is_nan());
-    // assert_eq!(inf.powi(3), inf);
-    // assert_eq!(neg_inf.powi(2), inf);
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_eq!(1.0f16.powi(1), 1.0);
+    assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
+    assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
+    assert_eq!(8.3f16.powi(0), 1.0);
+    assert!(nan.powi(2).is_nan());
+    assert_eq!(inf.powi(3), inf);
+    assert_eq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -813,6 +811,7 @@ fn test_clamp_max_is_nan() {
 }
 
 #[test]
+#[cfg(reliable_f16_math)]
 fn test_total_cmp() {
     use core::cmp::Ordering;
 
@@ -820,14 +819,13 @@ fn test_total_cmp() {
         1 << (f16::MANTISSA_DIGITS - 2)
     }
 
-    // FIXME(f16_f128): test subnormals when powf is available
-    // fn min_subnorm() -> f16 {
-    //     f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0)
-    // }
+    fn min_subnorm() -> f16 {
+        f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0)
+    }
 
-    // fn max_subnorm() -> f16 {
-    //     f16::MIN_POSITIVE - min_subnorm()
-    // }
+    fn max_subnorm() -> f16 {
+        f16::MIN_POSITIVE - min_subnorm()
+    }
 
     fn q_nan() -> f16 {
         f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask())
@@ -846,12 +844,12 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5));
     assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5));
     assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
     assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0));
     assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0));
-    // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
     assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE));
     assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5));
     assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0));
@@ -870,13 +868,13 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0));
     assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5));
     assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
     assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE));
     assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5));
     assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0));
     assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5));
@@ -894,13 +892,13 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5));
     assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0));
     assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5));
-    // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm()));
     assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0));
-    // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm()));
     assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE));
     assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5));
     assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0));
@@ -918,12 +916,12 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
@@ -940,12 +938,12 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 0f6fa2d291a..ec6ae31507e 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -3,7 +3,7 @@ cargo-features = ["public-dependency"]
 [package]
 name = "sysroot"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 # this is a dummy crate to ensure that all required crates appear in the sysroot
 [dependencies]
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index 241ef324b00..2a32a7dd76e 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -3,7 +3,7 @@ cargo-features = ["public-dependency"]
 [package]
 name = "test"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 [dependencies]
 getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml
index 66e8d1a3ffe..da60924c2b4 100644
--- a/library/unwind/Cargo.toml
+++ b/library/unwind/Cargo.toml
@@ -3,7 +3,7 @@ name = "unwind"
 version = "0.0.0"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
-edition = "2021"
+edition = "2024"
 include = [
   '/libunwind/*',
 ]
diff --git a/library/windows_targets/Cargo.toml b/library/windows_targets/Cargo.toml
index 94d7c821064..705c9e04381 100644
--- a/library/windows_targets/Cargo.toml
+++ b/library/windows_targets/Cargo.toml
@@ -2,7 +2,7 @@
 name = "windows-targets"
 description = "A drop-in replacement for the real windows-targets crate for use in std only."
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 [features]
 # Enable using raw-dylib for Windows imports.
diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs
index 939fab7d5fe..c7d158584eb 100644
--- a/library/windows_targets/src/lib.rs
+++ b/library/windows_targets/src/lib.rs
@@ -12,7 +12,7 @@ pub macro link {
     ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => (
         #[cfg_attr(not(target_arch = "x86"), link(name = $library, kind = "raw-dylib", modifiers = "+verbatim"))]
         #[cfg_attr(target_arch = "x86", link(name = $library, kind = "raw-dylib", modifiers = "+verbatim", import_name_type = "undecorated"))]
-        extern $abi {
+        unsafe extern $abi {
             $(#[link_name=$link_name])?
             pub fn $($function)*;
         }
@@ -26,7 +26,7 @@ pub macro link {
         // libraries below by using an empty extern block. This works because extern blocks are not
         // connected to the library given in the #[link] attribute.
         #[link(name = "kernel32")]
-        extern $abi {
+        unsafe extern $abi {
             $(#[link_name=$link_name])?
             pub fn $($function)*;
         }
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 18aa3119842..e67bc62a603 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -454,7 +454,6 @@ tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc"
 tool_check_step!(Clippy { path: "src/tools/clippy" });
 tool_check_step!(Miri { path: "src/tools/miri" });
 tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
-tool_check_step!(Rls { path: "src/tools/rls" });
 tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
 tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
 tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index fe8c89f7a53..d3ab215d1b5 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -346,7 +346,6 @@ lint_any!(
     OptDist, "src/tools/opt-dist", "opt-dist";
     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
     RemoteTestServer, "src/tools/remote-test-server", "remote-test-server";
-    Rls, "src/tools/rls", "rls";
     RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer";
     Rustdoc, "src/librustdoc", "clippy";
     Rustfmt, "src/tools/rustfmt", "rustfmt";
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 8cb3e3ed872..7c83c53d2c2 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -67,7 +67,7 @@ impl Std {
         self
     }
 
-    #[allow(clippy::wrong_self_convention)]
+    #[expect(clippy::wrong_self_convention)]
     pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
         self.is_for_mir_opt_tests = is_for_mir_opt_tests;
         self
@@ -194,11 +194,7 @@ impl Step for Std {
         trace!(?compiler_to_use);
 
         if compiler_to_use != compiler {
-            trace!(
-                ?compiler_to_use,
-                ?compiler,
-                "compiler != compiler_to_use, handling cross-compile scenario"
-            );
+            trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
 
             builder.ensure(Std::new(compiler_to_use, target));
             let msg = if compiler_to_use.host == target {
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index ec0edeab996..c393eb55c62 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1158,48 +1158,6 @@ impl Step for Cargo {
 }
 
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
-pub struct Rls {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
-}
-
-impl Step for Rls {
-    type Output = Option<GeneratedTarball>;
-    const ONLY_HOSTS: bool = true;
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let default = should_build_extended_tool(run.builder, "rls");
-        run.alias("rls").default_condition(default)
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Rls {
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.build,
-                run.target,
-            ),
-            target: run.target,
-        });
-    }
-
-    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
-        let target = self.target;
-
-        let rls = builder.ensure(tool::Rls { compiler, target });
-
-        let mut tarball = Tarball::new(builder, "rls", &target.triple);
-        tarball.set_overlay(OverlayKind::Rls);
-        tarball.is_preview(true);
-        tarball.add_file(rls.tool_path, "bin", 0o755);
-        tarball.add_legal_and_readme_to("share/doc/rls");
-        Some(tarball.generate())
-    }
-}
-
-#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct RustAnalyzer {
     pub compiler: Compiler,
     pub target: TargetSelection,
@@ -1528,7 +1486,6 @@ impl Step for Extended {
         add_component!("rust-json-docs" => JsonDocs { host: target });
         add_component!("cargo" => Cargo { compiler, target });
         add_component!("rustfmt" => Rustfmt { compiler, target });
-        add_component!("rls" => Rls { compiler, target });
         add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
         add_component!("llvm-components" => LlvmTools { target });
         add_component!("clippy" => Clippy { compiler, target });
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index f25dfaab0f1..45f9f52cb82 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -85,9 +85,7 @@ impl FromStr for Profile {
             "lib" | "library" => Ok(Profile::Library),
             "compiler" => Ok(Profile::Compiler),
             "maintainer" | "dist" | "user" => Ok(Profile::Dist),
-            "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
-                Ok(Profile::Tools)
-            }
+            "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" => Ok(Profile::Tools),
             "none" => Ok(Profile::None),
             "llvm" | "codegen" => Err("the \"llvm\" and \"codegen\" profiles have been removed,\
                 use \"compiler\" instead which has the same functionality"
@@ -584,10 +582,12 @@ Select which editor you would like to set up [default: None]: ";
             EditorKind::Emacs => &[
                 "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
                 "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
+                "b5dd299b93dca3ceeb9b335f929293cb3d4bf4977866fbe7ceeac2a8a9f99088",
             ],
             EditorKind::Helix => &[
                 "2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
                 "6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040",
+                "f252dcc30ca85a193a699581e5e929d5bd6c19d40d7a7ade5e257a9517a124a5",
             ],
             EditorKind::Vim | EditorKind::VsCode => &[
                 "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
@@ -600,10 +600,12 @@ Select which editor you would like to set up [default: None]: ";
                 "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
                 "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
                 "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
+                "e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717",
+            ],
+            EditorKind::Zed => &[
+                "bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c",
+                "a5380cf5dd9328731aecc5dfb240d16dac46ed272126b9728006151ef42f5909",
             ],
-            EditorKind::Zed => {
-                &["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"]
-            }
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index ba9b1b2fc33..6a6731cafc5 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -1,7 +1,5 @@
 //! Attempt to magically identify good tests to run
 
-#![cfg_attr(feature = "build-metrics", allow(unused))]
-
 use std::path::PathBuf;
 use std::str::FromStr;
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index e80f8f9a4b7..01e9abacc6b 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3377,7 +3377,7 @@ impl Step for CodegenCranelift {
         /*
         let mut prepare_cargo = build_cargo();
         prepare_cargo.arg("--").arg("prepare").arg("--download-dir").arg(&download_dir);
-        #[allow(deprecated)]
+        #[expect(deprecated)]
         builder.config.try_run(&mut prepare_cargo.into()).unwrap();
         */
 
@@ -3508,7 +3508,7 @@ impl Step for CodegenGCC {
         /*
         let mut prepare_cargo = build_cargo();
         prepare_cargo.arg("--").arg("prepare");
-        #[allow(deprecated)]
+        #[expect(deprecated)]
         builder.config.try_run(&mut prepare_cargo.into()).unwrap();
         */
 
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index e0cf2c12139..aaf6712102c 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -209,7 +209,7 @@ impl Step for ToolBuild {
     }
 }
 
-#[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this.
+#[expect(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this.
 pub fn prepare_tool_cargo(
     builder: &Builder<'_>,
     compiler: Compiler,
@@ -228,7 +228,6 @@ pub fn prepare_tool_cargo(
     let mut features = extra_features.to_vec();
     if builder.build.config.cargo_native_static {
         if path.ends_with("cargo")
-            || path.ends_with("rls")
             || path.ends_with("clippy")
             || path.ends_with("miri")
             || path.ends_with("rustfmt")
@@ -1025,7 +1024,7 @@ pub struct LibcxxVersionTool {
     pub target: TargetSelection,
 }
 
-#[allow(dead_code)]
+#[expect(dead_code)]
 #[derive(Debug, Clone)]
 pub enum LibcxxVersion {
     Gnu(usize),
@@ -1231,7 +1230,6 @@ tool_extended!(CargoMiri {
     stable: false,
     add_bins_to_sysroot: ["cargo-miri"]
 });
-tool_extended!(Rls { path: "src/tools/rls", tool_name: "rls", stable: true });
 tool_extended!(Rustfmt {
     path: "src/tools/rustfmt",
     tool_name: "rustfmt",
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 12dd40d14e9..62d23c4ae6b 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1045,8 +1045,11 @@ impl Builder<'_> {
         // so this line allows the use of custom libcs.
         cargo.env("LIBC_CHECK_CFG", "1");
 
+        let mut lint_flags = Vec::new();
+
+        // Lints for all in-tree code: compiler, rustdoc, cranelift, gcc,
+        // clippy, rustfmt, rust-analyzer, etc.
         if source_type == SourceType::InTree {
-            let mut lint_flags = Vec::new();
             // When extending this list, add the new lints to the RUSTFLAGS of the
             // build_bootstrap function of src/bootstrap/bootstrap.py as well as
             // some code doesn't go through this `rustc` wrapper.
@@ -1058,27 +1061,32 @@ impl Builder<'_> {
                 rustdocflags.arg("-Dwarnings");
             }
 
-            // This does not use RUSTFLAGS due to caching issues with Cargo.
-            // Clippy is treated as an "in tree" tool, but shares the same
-            // cache as other "submodule" tools. With these options set in
-            // RUSTFLAGS, that causes *every* shared dependency to be rebuilt.
-            // By injecting this into the rustc wrapper, this circumvents
-            // Cargo's fingerprint detection. This is fine because lint flags
-            // are always ignored in dependencies. Eventually this should be
-            // fixed via better support from Cargo.
-            cargo.env("RUSTC_LINT_FLAGS", lint_flags.join(" "));
-
             rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes");
         }
 
+        // Lints just for `compiler/` crates.
         if mode == Mode::Rustc {
-            rustflags.arg("-Wrustc::internal");
-            rustflags.arg("-Drustc::symbol_intern_string_literal");
+            lint_flags.push("-Wrustc::internal");
+            lint_flags.push("-Drustc::symbol_intern_string_literal");
             // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
             // of the individual lints are satisfied.
-            rustflags.arg("-Wkeyword_idents_2024");
-            rustflags.arg("-Wunsafe_op_in_unsafe_fn");
-        }
+            lint_flags.push("-Wkeyword_idents_2024");
+            lint_flags.push("-Wunreachable_pub");
+            lint_flags.push("-Wunsafe_op_in_unsafe_fn");
+        }
+
+        // This does not use RUSTFLAGS for two reasons.
+        // - Due to caching issues with Cargo. Clippy is treated as an "in
+        //   tree" tool, but shares the same cache as other "submodule" tools.
+        //   With these options set in RUSTFLAGS, that causes *every* shared
+        //   dependency to be rebuilt. By injecting this into the rustc
+        //   wrapper, this circumvents Cargo's fingerprint detection. This is
+        //   fine because lint flags are always ignored in dependencies.
+        //   Eventually this should be fixed via better support from Cargo.
+        // - RUSTFLAGS is ignored for proc macro crates that are being built on
+        //   the host (because `--target` is given). But we want the lint flags
+        //   to be applied to proc macro crates.
+        cargo.env("RUSTC_LINT_FLAGS", lint_flags.join(" "));
 
         if self.config.rust_frame_pointers {
             rustflags.arg("-Cforce-frame-pointers=true");
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 8e1cecfcd18..0b6b8513cc3 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -895,7 +895,6 @@ impl<'a> Builder<'a> {
                 tool::RemoteTestClient,
                 tool::RustInstaller,
                 tool::Cargo,
-                tool::Rls,
                 tool::RustAnalyzer,
                 tool::RustAnalyzerProcMacroSrv,
                 tool::Rustdoc,
@@ -938,7 +937,6 @@ impl<'a> Builder<'a> {
                 clippy::OptDist,
                 clippy::RemoteTestClient,
                 clippy::RemoteTestServer,
-                clippy::Rls,
                 clippy::RustAnalyzer,
                 clippy::Rustdoc,
                 clippy::Rustfmt,
@@ -956,7 +954,6 @@ impl<'a> Builder<'a> {
                 check::Miri,
                 check::CargoMiri,
                 check::MiroptTestTools,
-                check::Rls,
                 check::Rustfmt,
                 check::RustAnalyzer,
                 check::TestFloatParse,
@@ -1071,7 +1068,6 @@ impl<'a> Builder<'a> {
                 dist::Analysis,
                 dist::Src,
                 dist::Cargo,
-                dist::Rls,
                 dist::RustAnalyzer,
                 dist::Rustfmt,
                 dist::Clippy,
@@ -1289,7 +1285,6 @@ impl<'a> Builder<'a> {
         host: TargetSelection,
         target: TargetSelection,
     ) -> Compiler {
-        #![allow(clippy::let_and_return)]
         let mut resolved_compiler = if self.build.force_use_stage2(stage) {
             trace!(target: "COMPILER_FOR", ?stage, "force_use_stage2");
             self.compiler(2, self.config.build)
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index 9f09dd13f29..179e15e778b 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -1,4 +1,4 @@
-#[allow(clippy::module_inception)]
+#[expect(clippy::module_inception)]
 mod config;
 pub mod flags;
 #[cfg(test)]
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 95feb41ffd0..98eff664a5b 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -19,7 +19,7 @@ static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
 
 /// `Config::try_run` wrapper for this module to avoid warnings on `try_run`, since we don't have access to a `builder` yet.
 fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> {
-    #[allow(deprecated)]
+    #[expect(deprecated)]
     config.try_run(cmd)
 }
 
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 994ccabf0eb..8dfd1bbfd60 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -74,7 +74,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
 
 /// Extra `--check-cfg` to add when building the compiler or tools
 /// (Mode restriction, config name, config values (if any))
-#[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above.
+#[expect(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above.
 const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     (None, "bootstrap", None),
     (Some(Mode::Rustc), "llvm_enzyme", None),
@@ -253,7 +253,7 @@ pub enum Mode {
     /// Build a tool which uses the locally built rustc and the target std,
     /// placing the output in the "stageN-tools" directory. This is used for
     /// anything that needs a fully functional rustc, such as rustdoc, clippy,
-    /// cargo, rls, rustfmt, miri, etc.
+    /// cargo, rustfmt, miri, etc.
     ToolRustc,
 }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index ec27109c117..8036c592108 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -375,4 +375,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "There is now a new `gcc` config section that can be used to download GCC from CI using `gcc.download-ci-gcc = true`",
     },
+    ChangeInfo {
+        change_id: 126856,
+        severity: ChangeSeverity::Warning,
+        summary: "Removed `src/tools/rls` tool as it was deprecated long time ago.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 7eb9ab96c8a..d07300e21d0 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -125,7 +125,7 @@ impl BootstrapCommand {
         Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self }
     }
 
-    #[allow(dead_code)]
+    #[expect(dead_code)]
     pub fn fail_fast(self) -> Self {
         Self { failure_behavior: BehaviorOnFailure::Exit, ..self }
     }
@@ -280,7 +280,7 @@ impl CommandOutput {
         !self.is_success()
     }
 
-    #[allow(dead_code)]
+    #[expect(dead_code)]
     pub fn status(&self) -> Option<ExitStatus> {
         match self.status {
             CommandStatus::Finished(status) => Some(status),
@@ -332,7 +332,6 @@ impl Default for CommandOutput {
 
 /// Helper trait to format both Command and BootstrapCommand as a short execution line,
 /// without all the other details (e.g. environment variables).
-#[allow(unused)]
 pub trait FormatShortCmd {
     fn format_short_cmd(&self) -> String;
 }
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 57766fd63fb..885fff9c32c 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -76,7 +76,7 @@ impl BuildMetrics {
 
         // Consider all the stats gathered so far as the parent's.
         if !state.running_steps.is_empty() {
-            self.collect_stats(&mut *state);
+            self.collect_stats(&mut state);
         }
 
         state.system_info.refresh_cpu_usage();
@@ -102,7 +102,7 @@ impl BuildMetrics {
 
         let mut state = self.state.borrow_mut();
 
-        self.collect_stats(&mut *state);
+        self.collect_stats(&mut state);
 
         let step = state.running_steps.pop().unwrap();
         if state.running_steps.is_empty() {
@@ -224,6 +224,7 @@ impl BuildMetrics {
         t!(serde_json::to_writer(&mut file, &json));
     }
 
+    #[expect(clippy::only_used_in_recursion)]
     fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
         let mut children = Vec::new();
         children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child)));
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 843ea65e838..f1678bacc97 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -22,7 +22,6 @@ pub(crate) enum OverlayKind {
     Clippy,
     Miri,
     Rustfmt,
-    Rls,
     RustAnalyzer,
     RustcCodegenCranelift,
     LlvmBitcodeLinker,
@@ -56,7 +55,6 @@ impl OverlayKind {
                 "src/tools/rustfmt/LICENSE-APACHE",
                 "src/tools/rustfmt/LICENSE-MIT",
             ],
-            OverlayKind::Rls => &["src/tools/rls/README.md", "LICENSE-APACHE", "LICENSE-MIT"],
             OverlayKind::RustAnalyzer => &[
                 "src/tools/rust-analyzer/README.md",
                 "src/tools/rust-analyzer/LICENSE-APACHE",
@@ -90,7 +88,6 @@ impl OverlayKind {
             OverlayKind::Rustfmt => {
                 builder.rustfmt_info.version(builder, &builder.release_num("rustfmt"))
             }
-            OverlayKind::Rls => builder.release(&builder.release_num("rls")),
             OverlayKind::RustAnalyzer => builder
                 .rust_analyzer_info
                 .version(builder, &builder.release_num("rust-analyzer/crates/rust-analyzer")),
diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs
index 45a188fb234..0de8b740227 100644
--- a/src/ci/citool/src/jobs.rs
+++ b/src/ci/citool/src/jobs.rs
@@ -24,6 +24,8 @@ pub struct Job {
     /// Free additional disk space in the job, by removing unused packages.
     #[serde(default)]
     pub free_disk: Option<bool>,
+    /// Documentation link to a resource that could help people debug this CI job.
+    pub doc_url: Option<String>,
 }
 
 impl Job {
@@ -103,6 +105,8 @@ struct GithubActionsJob {
     continue_on_error: Option<bool>,
     #[serde(skip_serializing_if = "Option::is_none")]
     free_disk: Option<bool>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    doc_url: Option<String>,
 }
 
 /// Skip CI jobs that are not supposed to be executed on the given `channel`.
@@ -188,6 +192,7 @@ fn calculate_jobs(
                 env,
                 continue_on_error: job.continue_on_error,
                 free_disk: job.free_disk,
+                doc_url: job.doc_url,
             }
         })
         .collect();
diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs
index 1d81d58f893..788f5e7e4f6 100644
--- a/src/ci/citool/tests/jobs.rs
+++ b/src/ci/citool/tests/jobs.rs
@@ -40,7 +40,7 @@ try-job: dist-i686-msvc"#,
 fn pr_jobs() {
     let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234");
     insta::assert_snapshot!(stdout, @r#"
-    jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true}]
+    jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}]
     run_type=pr
     "#);
 }
diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml
index 56b9ced2071..ff4d1772f59 100644
--- a/src/ci/citool/tests/test-jobs.yml
+++ b/src/ci/citool/tests/test-jobs.yml
@@ -75,6 +75,7 @@ pr:
     <<: *job-linux-4c
   - name: mingw-check-tidy
     continue_on_error: true
+    doc_url: https://foo.bar
     <<: *job-linux-4c
 
 # Jobs that run when you perform a try build (@bors try)
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index eba55338ff8..d8c3625af28 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -267,11 +267,13 @@ auto:
     # nightly features to compile, and this job would fail if
     # executed on beta and stable.
     only_on_channel: nightly
+    doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html
     <<: *job-linux-8c
 
   # Tests integration with Rust for Linux.
   # Builds stage 1 compiler and tries to compile a few RfL examples with it.
   - name: x86_64-rust-for-linux
+    doc_url: https://rustc-dev-guide.rust-lang.org/tests/rust-for-linux.html
     <<: *job-linux-4c
 
   - name: x86_64-gnu
diff --git a/src/ci/run.sh b/src/ci/run.sh
index b874f71832d..823404ea632 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -6,6 +6,10 @@ if [ -n "$CI_JOB_NAME" ]; then
   echo "[CI_JOB_NAME=$CI_JOB_NAME]"
 fi
 
+if [ -n "$CI_JOB_DOC_URL" ]; then
+  echo "[CI_JOB_DOC_URL=$CI_JOB_DOC_URL]"
+fi
+
 if [ "$NO_CHANGE_USER" = "" ]; then
   if [ "$LOCAL_USER_ID" != "" ]; then
     id -u user &>/dev/null || useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
@@ -54,13 +58,8 @@ if [ "$FORCE_CI_RUSTC" == "" ]; then
     DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1
 fi
 
-if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \
-  isCiBranch automation/bors/try; then
-    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
-    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
-    HAS_METRICS=1
-fi
-
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-verbose-configure"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules"
@@ -266,14 +265,10 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
   $SRC/configure --set change-id=99999999
 
   # Save the build metrics before we wipe the directory
-  if [ "$HAS_METRICS" = 1 ]; then
-    mv build/metrics.json .
-  fi
+  mv build/metrics.json .
   rm -rf build
-  if [ "$HAS_METRICS" = 1 ]; then
-    mkdir build
-    mv metrics.json build
-  fi
+  mkdir build
+  mv metrics.json build
 
   CARGO_INCREMENTAL=0 ../x check
 fi
diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md
index 51893d537d7..75f5a9e2045 100644
--- a/src/doc/rustc-dev-guide/src/hir.md
+++ b/src/doc/rustc-dev-guide/src/hir.md
@@ -139,12 +139,12 @@ defined in the map. By matching on this, you can find out what sort of
 node the `HirId` referred to and also get a pointer to the data
 itself. Often, you know what sort of node `n` is – e.g. if you know
 that `n` must be some HIR expression, you can do
-[`tcx.hir().expect_expr(n)`][expect_expr], which will extract and return the
+[`tcx.hir_expect_expr(n)`][expect_expr], which will extract and return the
 [`&hir::Expr`][Expr], panicking if `n` is not in fact an expression.
 
 [find]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.find
 [`Node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.Node.html
-[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.expect_expr
+[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.expect_expr
 [Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Expr.html
 
 Finally, you can use the HIR map to find the parents of nodes, via
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 70880e0d61f..c74a9e98496 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -265,7 +265,7 @@ target | std | host | notes
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
 [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ |  | ARM64 Redox OS
 [`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? |  | ARM64 TEEOS |
-[`aarch64-unknown-trusty`](platform-support/trusty.md) | ? |  |
+[`aarch64-unknown-trusty`](platform-support/trusty.md) | ✓ |  |
 [`aarch64-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  |
 [`aarch64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | ARM64 VxWorks OS
 `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
@@ -290,7 +290,7 @@ target | std | host | notes
 [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | Armv7-A Linux with uClibc, softfloat
 [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat
 [`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float
-[`armv7-unknown-trusty`](platform-support/trusty.md) | ? |  |
+[`armv7-unknown-trusty`](platform-support/trusty.md) | ✓ |  |
 [`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ✓ |  | Armv7-A for VxWorks
 [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3
 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3, hardfloat
@@ -419,7 +419,7 @@ target | std | host | notes
 `x86_64-unknown-l4re-uclibc` | ? |  |
 [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * |  | 64-bit Linux with no libc
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
-[`x86_64-unknown-trusty`](platform-support/trusty.md) | ? |  |
+[`x86_64-unknown-trusty`](platform-support/trusty.md) | ✓ |  |
 `x86_64-uwp-windows-gnu` | ✓ |  |
 [`x86_64-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  |
 [`x86_64-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 64-bit Windows 7 support
diff --git a/src/doc/rustc/src/platform-support/trusty.md b/src/doc/rustc/src/platform-support/trusty.md
index 6b37543b600..73fcbbdddca 100644
--- a/src/doc/rustc/src/platform-support/trusty.md
+++ b/src/doc/rustc/src/platform-support/trusty.md
@@ -16,8 +16,10 @@ Environment (TEE) for Android.
 
 These targets are cross-compiled. They have no special requirements for the host.
 
-Support for the standard library is work-in-progress. It is expected that
-they will support alloc with the default allocator, and partially support std.
+Trusty targets have partial support for the standard library: `alloc` is fully
+supported and `std` has limited support that excludes things like filesystem
+access, network I/O, and spawning processes/threads. File descriptors are
+supported for the purpose of IPC.
 
 Trusty uses the ELF file format.
 
diff --git a/src/etc/rust_analyzer_eglot.el b/src/etc/rust_analyzer_eglot.el
index 7b4309f8e18..6b40371d9af 100644
--- a/src/etc/rust_analyzer_eglot.el
+++ b/src/etc/rust_analyzer_eglot.el
@@ -8,7 +8,6 @@
                                                          "check"
                                                          "--json-output"])
                  :linkedProjects ["Cargo.toml"
-                                  "src/tools/x/Cargo.toml"
                                   "src/bootstrap/Cargo.toml"
                                   "src/tools/rust-analyzer/Cargo.toml"
                                   "compiler/rustc_codegen_cranelift/Cargo.toml"
diff --git a/src/etc/rust_analyzer_helix.toml b/src/etc/rust_analyzer_helix.toml
index afddd089eb1..05fc7716a72 100644
--- a/src/etc/rust_analyzer_helix.toml
+++ b/src/etc/rust_analyzer_helix.toml
@@ -15,7 +15,6 @@ linkedProjects = [
     "library/Cargo.toml",
     "src/bootstrap/Cargo.toml",
     "src/tools/rust-analyzer/Cargo.toml",
-    "src/tools/x/Cargo.toml",
 ]
 
 [language-server.rust-analyzer.config.check]
diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json
index b104356d44c..da7d326a512 100644
--- a/src/etc/rust_analyzer_settings.json
+++ b/src/etc/rust_analyzer_settings.json
@@ -10,7 +10,6 @@
     "rust-analyzer.linkedProjects": [
         "Cargo.toml",
         "library/Cargo.toml",
-        "src/tools/x/Cargo.toml",
         "src/bootstrap/Cargo.toml",
         "src/tools/rust-analyzer/Cargo.toml",
         "compiler/rustc_codegen_cranelift/Cargo.toml",
diff --git a/src/etc/rust_analyzer_zed.json b/src/etc/rust_analyzer_zed.json
index 469ea050621..abc6ddbc213 100644
--- a/src/etc/rust_analyzer_zed.json
+++ b/src/etc/rust_analyzer_zed.json
@@ -22,7 +22,6 @@
         "linkedProjects": [
           "Cargo.toml",
           "library/Cargo.toml",
-          "src/tools/x/Cargo.toml",
           "src/bootstrap/Cargo.toml",
           "src/tools/rust-analyzer/Cargo.toml",
           "compiler/rustc_codegen_cranelift/Cargo.toml",
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 8c6ea00d489..e973b89b237 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -181,7 +181,7 @@ pub(crate) fn try_inline_glob(
                 .filter_map(|child| child.res.opt_def_id())
                 .filter(|def_id| !cx.tcx.is_doc_hidden(def_id))
                 .collect();
-            let attrs = cx.tcx.hir().attrs(import.hir_id());
+            let attrs = cx.tcx.hir_attrs(import.hir_id());
             let mut items = build_module_items(
                 cx,
                 did,
@@ -455,7 +455,7 @@ pub(crate) fn build_impl(
     }
 
     let impl_item = match did.as_local() {
-        Some(did) => match &tcx.hir().expect_item(did).kind {
+        Some(did) => match &tcx.hir_expect_item(did).kind {
             hir::ItemKind::Impl(impl_) => Some(impl_),
             _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
         },
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 97ff4c2ef40..0f476c8c9ff 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -112,7 +112,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| {
         let Some(def_id) = res.opt_def_id() else { return Vec::new() };
         let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
-        let import = cx.tcx.hir().expect_item(*local_import_id);
+        let import = cx.tcx.hir_expect_item(*local_import_id);
         match import.kind {
             hir::ItemKind::Use(path, kind) => {
                 let hir::UsePath { segments, span, .. } = *path;
@@ -125,7 +125,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
         // Now we actually lower the imports, skipping everything else.
         if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
-            let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+            let name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id()));
             clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
         } else {
             // skip everything else
@@ -231,7 +231,7 @@ fn clean_generic_bound<'tcx>(
             GenericBound::TraitBound(clean_poly_trait_ref(t, cx), t.modifiers)
         }
         hir::GenericBound::Use(args, ..) => {
-            GenericBound::Use(args.iter().map(|arg| arg.name()).collect())
+            GenericBound::Use(args.iter().map(|arg| clean_precise_capturing_arg(arg, cx)).collect())
         }
     })
 }
@@ -286,6 +286,18 @@ fn clean_lifetime(lifetime: &hir::Lifetime, cx: &DocContext<'_>) -> Lifetime {
     Lifetime(lifetime.ident.name)
 }
 
+pub(crate) fn clean_precise_capturing_arg(
+    arg: &hir::PreciseCapturingArg<'_>,
+    cx: &DocContext<'_>,
+) -> PreciseCapturingArg {
+    match arg {
+        hir::PreciseCapturingArg::Lifetime(lt) => {
+            PreciseCapturingArg::Lifetime(clean_lifetime(lt, cx))
+        }
+        hir::PreciseCapturingArg::Param(param) => PreciseCapturingArg::Param(param.ident.name),
+    }
+}
+
 pub(crate) fn clean_const<'tcx>(
     constant: &hir::ConstArg<'tcx>,
     _cx: &mut DocContext<'tcx>,
@@ -986,7 +998,7 @@ fn clean_proc_macro<'tcx>(
     kind: MacroKind,
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     if kind == MacroKind::Derive
         && let Some(derive_name) =
             hir_attr_lists(attrs, sym::proc_macro_derive).find_map(|mi| mi.ident())
@@ -1019,7 +1031,7 @@ fn clean_fn_or_proc_macro<'tcx>(
     name: &mut Symbol,
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     let macro_kind = attrs.iter().find_map(|a| {
         if a.has_name(sym::proc_macro) {
             Some(MacroKind::Bang)
@@ -1756,7 +1768,7 @@ fn maybe_expand_private_type_alias<'tcx>(
     let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id())
         && !cx.current_type_aliases.contains_key(&def_id.to_def_id())
     {
-        &cx.tcx.hir().expect_item(def_id).kind
+        &cx.tcx.hir_expect_item(def_id).kind
     } else {
         return None;
     };
@@ -2364,7 +2376,18 @@ fn clean_middle_opaque_bounds<'tcx>(
     }
 
     if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
-        bounds.push(GenericBound::Use(args.to_vec()));
+        bounds.push(GenericBound::Use(
+            args.iter()
+                .map(|arg| match arg {
+                    hir::PreciseCapturingArgKind::Lifetime(lt) => {
+                        PreciseCapturingArg::Lifetime(Lifetime(*lt))
+                    }
+                    hir::PreciseCapturingArgKind::Param(param) => {
+                        PreciseCapturingArg::Param(*param)
+                    }
+                })
+                .collect(),
+        ));
     }
 
     ImplTrait(bounds)
@@ -2762,7 +2785,7 @@ fn clean_maybe_renamed_item<'tcx>(
     use hir::ItemKind;
 
     let def_id = item.owner_id.to_def_id();
-    let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+    let mut name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id()));
     cx.with_param_env(def_id, |cx| {
         let kind = match item.kind {
             ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
@@ -2937,7 +2960,7 @@ fn clean_extern_crate<'tcx>(
     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.owner_id.def_id).unwrap_or(LOCAL_CRATE);
     // this is the ID of the crate itself
     let crate_def_id = cnum.as_def_id();
-    let attrs = cx.tcx.hir().attrs(krate.hir_id());
+    let attrs = cx.tcx.hir_attrs(krate.hir_id());
     let ty_vis = cx.tcx.visibility(krate.owner_id);
     let please_inline = ty_vis.is_public()
         && attrs.iter().any(|a| {
@@ -3006,7 +3029,7 @@ fn clean_use_statement_inner<'tcx>(
     }
 
     let visibility = cx.tcx.visibility(import.owner_id);
-    let attrs = cx.tcx.hir().attrs(import.hir_id());
+    let attrs = cx.tcx.hir_attrs(import.hir_id());
     let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline);
     let pub_underscore = visibility.is_public() && name == kw::Underscore;
     let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 9e9cd528834..228d9108e4e 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1240,7 +1240,7 @@ pub(crate) enum GenericBound {
     TraitBound(PolyTrait, hir::TraitBoundModifiers),
     Outlives(Lifetime),
     /// `use<'a, T>` precise-capturing bound syntax
-    Use(Vec<Symbol>),
+    Use(Vec<PreciseCapturingArg>),
 }
 
 impl GenericBound {
@@ -1304,6 +1304,21 @@ impl Lifetime {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+pub(crate) enum PreciseCapturingArg {
+    Lifetime(Lifetime),
+    Param(Symbol),
+}
+
+impl PreciseCapturingArg {
+    pub(crate) fn name(self) -> Symbol {
+        match self {
+            PreciseCapturingArg::Lifetime(lt) => lt.0,
+            PreciseCapturingArg::Param(param) => param,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub(crate) enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 9cf471733f9..23a2bcd9011 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -103,6 +103,8 @@ pub(crate) struct Options {
     /// compiling doctests from the crate.
     pub(crate) edition: Edition,
     /// The path to the sysroot. Used during the compilation process.
+    pub(crate) sysroot: PathBuf,
+    /// Has the same value as `sysroot` except is `None` when the user didn't pass `---sysroot`.
     pub(crate) maybe_sysroot: Option<PathBuf>,
     /// Lint information passed over the command-line.
     pub(crate) lint_opts: Vec<(String, Level)>,
@@ -202,6 +204,7 @@ impl fmt::Debug for Options {
             .field("unstable_options", &"...")
             .field("target", &self.target)
             .field("edition", &self.edition)
+            .field("sysroot", &self.sysroot)
             .field("maybe_sysroot", &self.maybe_sysroot)
             .field("lint_opts", &self.lint_opts)
             .field("describe_lints", &self.describe_lints)
@@ -729,12 +732,7 @@ impl Options {
         let target = parse_target_triple(early_dcx, matches);
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
 
-        let sysroot = match &maybe_sysroot {
-            Some(s) => s.clone(),
-            None => {
-                rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
-            }
-        };
+        let sysroot = rustc_session::filesearch::materialize_sysroot(maybe_sysroot.clone());
 
         let libs = matches
             .opt_strs("L")
@@ -834,6 +832,7 @@ impl Options {
             unstable_opts_strs,
             target,
             edition,
+            sysroot,
             maybe_sysroot,
             lint_opts,
             describe_lints,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 719f1f978fe..c47e42670c9 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -210,7 +210,7 @@ pub(crate) fn create_config(
         unstable_opts,
         target,
         edition,
-        maybe_sysroot,
+        sysroot,
         lint_opts,
         describe_lints,
         lint_cap,
@@ -253,7 +253,7 @@ pub(crate) fn create_config(
     let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
     // plays with error output here!
     let sessopts = config::Options {
-        maybe_sysroot,
+        sysroot,
         search_paths: libs,
         crate_types,
         lint_opts,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 88af9a7388c..a2808bddb3a 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -158,7 +158,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
         if options.proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
 
     let sessopts = config::Options {
-        maybe_sysroot: options.maybe_sysroot.clone(),
+        sysroot: options.sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types,
         lint_opts,
@@ -216,7 +216,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
 
         let collector = rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| {
             let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
-            let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
+            let crate_attrs = tcx.hir_attrs(CRATE_HIR_ID);
             let opts = scrape_test_config(crate_name, crate_attrs, args_path);
             let enable_per_target_ignores = options.enable_per_target_ignores;
 
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 907e2a3eb2f..18ad442d017 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -95,7 +95,7 @@ impl HirCollector<'_> {
         sp: Span,
         nested: F,
     ) {
-        let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
+        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()))
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 8b8439a2535..e93b9eb272a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -283,7 +283,7 @@ impl clean::GenericBound {
                 } else {
                     f.write_str("use&lt;")?;
                 }
-                args.iter().joined(", ", f)?;
+                args.iter().map(|arg| arg.name()).joined(", ", f)?;
                 if f.alternate() { f.write_str(">") } else { f.write_str("&gt;") }
             }
         })
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index edfcc1291b9..4150c5609a9 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1,5 +1,5 @@
 // Local js definitions:
-/* global addClass, getSettingValue, hasClass, searchState, updateLocalStorage */
+/* global addClass, getSettingValue, hasClass, updateLocalStorage */
 /* global onEachLazy, removeClass, getVar */
 
 "use strict";
@@ -121,12 +121,9 @@ function getNakedUrl() {
  * doesn't have a parent node.
  *
  * @param {HTMLElement} newNode
- * @param {HTMLElement} referenceNode
+ * @param {HTMLElement & { parentNode: HTMLElement }} referenceNode
  */
 function insertAfter(newNode, referenceNode) {
-    // You're not allowed to pass an element with no parent.
-    // I dunno how to make TS's typechecker see that.
-    // @ts-expect-error
     referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
 }
 
@@ -305,11 +302,10 @@ function preLoadCss(cssUrl) {
                 window.searchState.timeout = null;
             }
         },
-        // @ts-expect-error
         isDisplayed: () => {
             const outputElement = window.searchState.outputElement();
-            return outputElement &&
-                outputElement.parentElement &&
+            return !!outputElement &&
+                !!outputElement.parentElement &&
                 outputElement.parentElement.id === ALTERNATIVE_DISPLAY_ID;
         },
         // Sets the focus on the search bar at the top of the page
@@ -325,8 +321,6 @@ function preLoadCss(cssUrl) {
                 search = window.searchState.outputElement();
             }
             switchDisplayedElement(search);
-            // @ts-expect-error
-            window.searchState.mouseMovedAfterSearch = false;
             document.title = window.searchState.title;
         },
         removeQueryParameters: () => {
@@ -503,34 +497,40 @@ function preLoadCss(cssUrl) {
         handleHashes(ev);
     }
 
-    // @ts-expect-error
+    /**
+     * @param {HTMLElement|null} elem
+     */
     function openParentDetails(elem) {
         while (elem) {
             if (elem.tagName === "DETAILS") {
+                // @ts-expect-error
                 elem.open = true;
             }
-            elem = elem.parentNode;
+            elem = elem.parentElement;
         }
     }
 
-    // @ts-expect-error
+    /**
+     * @param {string} id
+     */
     function expandSection(id) {
         openParentDetails(document.getElementById(id));
     }
 
-    // @ts-expect-error
+    /**
+     * @param {KeyboardEvent} ev
+     */
     function handleEscape(ev) {
-        // @ts-expect-error
-        searchState.clearInputTimeout();
-        // @ts-expect-error
-        searchState.hideResults();
+        window.searchState.clearInputTimeout();
+        window.searchState.hideResults();
         ev.preventDefault();
-        // @ts-expect-error
-        searchState.defocus();
+        window.searchState.defocus();
         window.hideAllModals(true); // true = reset focus for tooltips
     }
 
-    // @ts-expect-error
+    /**
+     * @param {KeyboardEvent} ev
+     */
     function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
         const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -538,8 +538,8 @@ function preLoadCss(cssUrl) {
             return;
         }
 
-        // @ts-expect-error
-        if (document.activeElement.tagName === "INPUT" &&
+        if (document.activeElement &&
+            document.activeElement.tagName === "INPUT" &&
             // @ts-expect-error
             document.activeElement.type !== "checkbox" &&
             // @ts-expect-error
@@ -559,8 +559,7 @@ function preLoadCss(cssUrl) {
             case "S":
             case "/":
                 ev.preventDefault();
-                // @ts-expect-error
-                searchState.focus();
+                window.searchState.focus();
                 break;
 
             case "+":
@@ -586,7 +585,6 @@ function preLoadCss(cssUrl) {
     document.addEventListener("keydown", handleShortcut);
 
     function addSidebarItems() {
-        // @ts-expect-error
         if (!window.SIDEBAR_ITEMS) {
             return;
         }
@@ -675,7 +673,6 @@ function preLoadCss(cssUrl) {
     }
 
     // <https://github.com/search?q=repo%3Arust-lang%2Frust+[RUSTDOCIMPL]+trait.impl&type=code>
-    // @ts-expect-error
     window.register_implementors = imp => {
         const implementors = document.getElementById("implementors-list");
         const synthetic_implementors = document.getElementById("synthetic-implementors-list");
@@ -767,9 +764,7 @@ function preLoadCss(cssUrl) {
             }
         }
     };
-    // @ts-expect-error
     if (window.pending_implementors) {
-        // @ts-expect-error
         window.register_implementors(window.pending_implementors);
     }
 
@@ -802,16 +797,14 @@ function preLoadCss(cssUrl) {
      *
      * - After processing all of the impls, it sorts the sidebar items by name.
      *
-     * @param {{[cratename: string]: Array<Array<string|0>>}} imp
+     * @param {rustdoc.TypeImpls} imp
      */
-    // @ts-expect-error
     window.register_type_impls = imp => {
         // @ts-expect-error
         if (!imp || !imp[window.currentCrate]) {
             return;
         }
-        // @ts-expect-error
-        window.pending_type_impls = null;
+        window.pending_type_impls = undefined;
         const idMap = new Map();
 
         let implementations = document.getElementById("implementations-list");
@@ -997,9 +990,7 @@ function preLoadCss(cssUrl) {
             list.replaceChildren(...newChildren);
         }
     };
-    // @ts-expect-error
     if (window.pending_type_impls) {
-        // @ts-expect-error
         window.register_type_impls(window.pending_type_impls);
     }
 
@@ -1695,8 +1686,7 @@ function preLoadCss(cssUrl) {
     addSidebarCrates();
     onHashChange(null);
     window.addEventListener("hashchange", onHashChange);
-    // @ts-expect-error
-    searchState.setup();
+    window.searchState.setup();
 }());
 
 // Hide, show, and resize the sidebar
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index 1554c045a32..4b43c00730d 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -7,6 +7,8 @@ declare global {
     interface Window {
         /** Make the current theme easy to find */
         currentTheme: HTMLLinkElement|null;
+        /** Generated in `render/context.rs` */
+        SIDEBAR_ITEMS?: { [key: string]: string[] };
         /** Used by the popover tooltip code. */
         RUSTDOC_TOOLTIP_HOVER_MS: number;
         /** Used by the popover tooltip code. */
@@ -42,6 +44,17 @@ declare global {
          * Set up event listeners for a scraped source example.
          */
         updateScrapedExample?: function(HTMLElement, HTMLElement),
+        /**
+         * register trait implementors, called by code generated in
+         * `write_shared.rs`
+         */
+        register_implementors?: function(rustdoc.Implementors): void,
+        /**
+         * fallback in case `register_implementors` isn't defined yet.
+         */
+        pending_implementors?: rustdoc.Implementors,
+        register_type_impls?: function(rustdoc.TypeImpls): void,
+        pending_type_impls?: rustdoc.TypeImpls,
     }
     interface HTMLElement {
         /** Used by the popover tooltip code. */
@@ -413,4 +426,16 @@ declare namespace rustdoc {
     };
 
     type VlqData = VlqData[] | number;
+
+    /**
+     * Maps from crate names to trait implementation data.
+     * Provied by generated `trait.impl` files.
+     */
+    type Implementors = {
+        [key: string]: Array<[string, number, Array<string>]>
+    }
+
+    type TypeImpls = {
+        [cratename: string]: Array<Array<string|0>>
+    }
 }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 9606ba76991..6369433a4b5 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -7,14 +7,13 @@
 use rustc_abi::ExternAbi;
 use rustc_ast::ast;
 use rustc_attr_parsing::DeprecatedSince;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_metadata::rendered_const;
 use rustc_middle::{bug, ty};
-use rustc_span::{Pos, Symbol, sym};
+use rustc_span::{Pos, Symbol};
 use rustdoc_json_types::*;
 
-use super::FullItemId;
 use crate::clean::{self, ItemId};
 use crate::formats::FormatRenderer;
 use crate::formats::item_type::ItemType;
@@ -108,67 +107,6 @@ impl JsonRenderer<'_> {
         }
     }
 
-    pub(crate) fn id_from_item_default(&self, item_id: ItemId) -> Id {
-        self.id_from_item_inner(item_id, None, None)
-    }
-
-    pub(crate) fn id_from_item_inner(
-        &self,
-        item_id: ItemId,
-        name: Option<Symbol>,
-        extra: Option<Id>,
-    ) -> Id {
-        let make_part = |def_id: DefId, name: Option<Symbol>, extra: Option<Id>| {
-            let name = match name {
-                Some(name) => Some(name),
-                None => {
-                    // We need this workaround because primitive types' DefId actually refers to
-                    // their parent module, which isn't present in the output JSON items. So
-                    // instead, we directly get the primitive symbol
-                    if matches!(self.tcx.def_kind(def_id), DefKind::Mod)
-                        && let Some(prim) = self
-                            .tcx
-                            .get_attrs(def_id, sym::rustc_doc_primitive)
-                            .find_map(|attr| attr.value_str())
-                    {
-                        Some(prim)
-                    } else {
-                        self.tcx.opt_item_name(def_id)
-                    }
-                }
-            };
-
-            FullItemId { def_id, name, extra }
-        };
-
-        let key = match item_id {
-            ItemId::DefId(did) => (make_part(did, name, extra), None),
-            ItemId::Blanket { for_, impl_id } => {
-                (make_part(impl_id, None, None), Some(make_part(for_, name, extra)))
-            }
-            ItemId::Auto { for_, trait_ } => {
-                (make_part(trait_, None, None), Some(make_part(for_, name, extra)))
-            }
-        };
-
-        let mut interner = self.id_interner.borrow_mut();
-        let len = interner.len();
-        *interner
-            .entry(key)
-            .or_insert_with(|| Id(len.try_into().expect("too many items in a crate")))
-    }
-
-    pub(crate) fn id_from_item(&self, item: &clean::Item) -> Id {
-        match item.kind {
-            clean::ItemKind::ImportItem(ref import) => {
-                let extra =
-                    import.source.did.map(ItemId::from).map(|i| self.id_from_item_default(i));
-                self.id_from_item_inner(item.item_id, item.name, extra)
-            }
-            _ => self.id_from_item_inner(item.item_id, item.name, None),
-        }
-    }
-
     fn ids(&self, items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
         items
             .into_iter()
@@ -548,7 +486,18 @@ impl FromClean<clean::GenericBound> for GenericBound {
                 }
             }
             Outlives(lifetime) => GenericBound::Outlives(convert_lifetime(lifetime)),
-            Use(args) => GenericBound::Use(args.into_iter().map(|arg| arg.to_string()).collect()),
+            Use(args) => GenericBound::Use(
+                args.iter()
+                    .map(|arg| match arg {
+                        clean::PreciseCapturingArg::Lifetime(lt) => {
+                            PreciseCapturingArg::Lifetime(convert_lifetime(*lt))
+                        }
+                        clean::PreciseCapturingArg::Param(param) => {
+                            PreciseCapturingArg::Param(param.to_string())
+                        }
+                    })
+                    .collect(),
+            ),
         }
     }
 }
diff --git a/src/librustdoc/json/ids.rs b/src/librustdoc/json/ids.rs
new file mode 100644
index 00000000000..737148bad4e
--- /dev/null
+++ b/src/librustdoc/json/ids.rs
@@ -0,0 +1,122 @@
+//! Id handling for rustdoc-json.
+//!
+//! Manages the creation of [`rustdoc_json_types::Id`] and the
+//! fact that these don't correspond exactly to [`DefId`], because
+//! [`rustdoc_json_types::Item`] doesn't correspond exactly to what
+//! other phases think of as an "item".
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_span::{Symbol, sym};
+use rustdoc_json_types as types;
+
+use super::JsonRenderer;
+use crate::clean;
+
+pub(super) type IdInterner = FxHashMap<FullItemId, types::Id>;
+
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+/// An uninterned id.
+///
+/// Each one corresponds to exactly one of both:
+/// 1. [`rustdoc_json_types::Item`].
+/// 2. [`rustdoc_json_types::Id`] transitively (as each `Item` has an `Id`).
+///
+/// It's *broadly* equivalent to a [`DefId`], but needs slightly more information
+/// to fully disambiguate items, because sometimes we choose to split a single HIR
+/// item into multiple JSON items, or have items with no corresponding HIR item.
+pub(super) struct FullItemId {
+    /// The "main" id of the item.
+    ///
+    /// In most cases this uniquely identifies the item, the other fields are just
+    /// used for edge-cases.
+    def_id: DefId,
+
+    /// An extra [`DefId`], which we need for:
+    ///
+    /// 1. Auto-trait impls synthesized by rustdoc.
+    /// 2. Blanket impls synthesized by rustdoc.
+    /// 3. Splitting of reexports of multiple items.
+    ///
+    ///    E.g:
+    ///
+    ///    ```rust
+    ///    mod module {
+    ///        pub struct Foo {} // Exists in type namespace
+    ///        pub fn Foo(){} // Exists in value namespace
+    ///    }
+    ///
+    ///    pub use module::Foo; // Imports both items
+    ///    ```
+    ///
+    ///    In HIR, the `pub use` is just 1 item, but in rustdoc-json it's 2, so
+    ///    we need to disambiguate.
+    extra_id: Option<DefId>,
+
+    /// Needed for `#[rustc_doc_primitive]` modules.
+    ///
+    /// For these, 1 [`DefId`] is used for both the primitive and the fake-module
+    /// that holds its docs.
+    ///
+    /// N.B. This only matters when documenting the standard library with
+    /// `--document-private-items`. Maybe we should delete that module, and
+    /// remove this.
+    name: Option<Symbol>,
+}
+
+impl JsonRenderer<'_> {
+    pub(crate) fn id_from_item_default(&self, item_id: clean::ItemId) -> types::Id {
+        self.id_from_item_inner(item_id, None, None)
+    }
+
+    fn id_from_item_inner(
+        &self,
+        item_id: clean::ItemId,
+        name: Option<Symbol>,
+        imported_id: Option<DefId>,
+    ) -> types::Id {
+        let (def_id, extra_id) = match item_id {
+            clean::ItemId::DefId(did) => (did, imported_id),
+            clean::ItemId::Blanket { for_, impl_id } => (for_, Some(impl_id)),
+            clean::ItemId::Auto { for_, trait_ } => (for_, Some(trait_)),
+        };
+
+        let name = match name {
+            Some(name) => Some(name),
+            None => {
+                // We need this workaround because primitive types' DefId actually refers to
+                // their parent module, which isn't present in the output JSON items. So
+                // instead, we directly get the primitive symbol
+                if matches!(self.tcx.def_kind(def_id), DefKind::Mod)
+                    && let Some(prim) = self
+                        .tcx
+                        .get_attrs(def_id, sym::rustc_doc_primitive)
+                        .find_map(|attr| attr.value_str())
+                {
+                    Some(prim)
+                } else {
+                    self.tcx.opt_item_name(def_id)
+                }
+            }
+        };
+
+        let key = FullItemId { def_id, extra_id, name };
+
+        let mut interner = self.id_interner.borrow_mut();
+        let len = interner.len();
+        *interner
+            .entry(key)
+            .or_insert_with(|| types::Id(len.try_into().expect("too many items in a crate")))
+    }
+
+    pub(crate) fn id_from_item(&self, item: &clean::Item) -> types::Id {
+        match item.kind {
+            clean::ItemKind::ImportItem(ref import) => {
+                let imported_id = import.source.did;
+                self.id_from_item_inner(item.item_id, item.name, imported_id)
+            }
+            _ => self.id_from_item_inner(item.item_id, item.name, None),
+        }
+    }
+}
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 6f8cf25554f..ba27eed7c11 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -5,6 +5,7 @@
 //! docs for usage and details.
 
 mod conversions;
+mod ids;
 mod import_finder;
 
 use std::cell::RefCell;
@@ -16,7 +17,6 @@ use std::rc::Rc;
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::Symbol;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustdoc_json_types as types;
 // It's important to use the FxHashMap from rustdoc_json_types here, instead of
@@ -35,14 +35,6 @@ use crate::formats::cache::Cache;
 use crate::json::conversions::IntoJson;
 use crate::{clean, try_err};
 
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
-struct FullItemId {
-    def_id: DefId,
-    name: Option<Symbol>,
-    /// Used to distinguish imports of different items with the same name
-    extra: Option<types::Id>,
-}
-
 #[derive(Clone)]
 pub(crate) struct JsonRenderer<'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -55,7 +47,7 @@ pub(crate) struct JsonRenderer<'tcx> {
     out_dir: Option<PathBuf>,
     cache: Rc<Cache>,
     imported_items: DefIdSet,
-    id_interner: Rc<RefCell<FxHashMap<(FullItemId, Option<FullItemId>), types::Id>>>,
+    id_interner: Rc<RefCell<ids::IdInterner>>,
 }
 
 impl<'tcx> JsonRenderer<'tcx> {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7b6921afa08..68e381fa3f1 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 && self.cx.tcx.has_attr(def_id, sym::macro_export)
                 && inserted.insert(def_id)
             {
-                let item = self.cx.tcx.hir().expect_item(local_def_id);
+                let item = self.cx.tcx.hir_expect_item(local_def_id);
                 top_level_module
                     .items
                     .insert((local_def_id, Some(item.ident.name)), (item, None, None));
@@ -153,8 +153,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.cx.cache.hidden_cfg = self
             .cx
             .tcx
-            .hir()
-            .attrs(CRATE_HIR_ID)
+            .hir_attrs(CRATE_HIR_ID)
             .iter()
             .filter(|attr| attr.has_name(sym::doc))
             .flat_map(|attr| attr.meta_item_list().into_iter().flatten())
@@ -245,7 +244,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         };
 
         let document_hidden = self.cx.render_options.document_hidden;
-        let use_attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
+        let use_attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
         // Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
         let is_no_inline = hir_attr_lists(use_attrs, sym::doc).has_word(sym::no_inline)
             || (document_hidden && hir_attr_lists(use_attrs, sym::doc).has_word(sym::hidden));
@@ -449,7 +448,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                         continue;
                     }
 
-                    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id));
+                    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id));
 
                     // If there was a private module in the current path then don't bother inlining
                     // anything as it will probably be stripped anyway.
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 8f6496e9626..8ec7cffe066 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 = 40;
+pub const FORMAT_VERSION: u32 = 41;
 
 /// The root of the emitted JSON blob.
 ///
@@ -909,7 +909,7 @@ pub enum GenericBound {
     /// ```
     Outlives(String),
     /// `use<'a, T>` precise-capturing bound syntax
-    Use(Vec<String>),
+    Use(Vec<PreciseCapturingArg>),
 }
 
 /// A set of modifiers applied to a trait.
@@ -927,6 +927,22 @@ pub enum TraitBoundModifier {
     MaybeConst,
 }
 
+/// One precise capturing argument. See [the rust reference](https://doc.rust-lang.org/reference/types/impl-trait.html#precise-capturing).
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum PreciseCapturingArg {
+    /// A lifetime.
+    /// ```rust
+    /// pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
+    /// //                                                        ^^
+    Lifetime(String),
+    /// A type or constant parameter.
+    /// ```rust
+    /// pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
+    /// //                                                            ^  ^
+    Param(String),
+}
+
 /// Either a type or a constant, usually stored as the right-hand side of an equation in places like
 /// [`AssocItemConstraint`]
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index dfc8f3bc7e0..741d7e3fa16 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -386,7 +386,6 @@ impl Builder {
         // NOTE: this profile is effectively deprecated; do not add new components to it.
         let mut complete = default;
         complete.extend([
-            Rls,
             RustAnalyzer,
             RustSrc,
             LlvmTools,
@@ -475,7 +474,6 @@ impl Builder {
                 // but might be marked as unavailable if they weren't built.
                 PkgType::Clippy
                 | PkgType::Miri
-                | PkgType::Rls
                 | PkgType::RustAnalyzer
                 | PkgType::Rustfmt
                 | PkgType::LlvmTools
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 495cab582eb..6ef8a0e83de 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -51,7 +51,6 @@ pkg_type! {
     Cargo = "cargo",
     HtmlDocs = "rust-docs",
     RustAnalysis = "rust-analysis",
-    Rls = "rls"; preview = true,
     RustAnalyzer = "rust-analyzer"; preview = true,
     Clippy = "clippy"; preview = true,
     Rustfmt = "rustfmt"; preview = true,
@@ -77,7 +76,6 @@ impl PkgType {
     fn should_use_rust_version(&self) -> bool {
         match self {
             PkgType::Cargo => false,
-            PkgType::Rls => false,
             PkgType::RustAnalyzer => false,
             PkgType::Clippy => false,
             PkgType::Rustfmt => false,
@@ -118,7 +116,6 @@ impl PkgType {
             HtmlDocs => HOSTS,
             JsonDocs => HOSTS,
             RustSrc => &["*"],
-            Rls => HOSTS,
             RustAnalyzer => HOSTS,
             Clippy => HOSTS,
             Miri => HOSTS,
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 2b59c218d57..f9a2f011a14 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -465,7 +465,7 @@ impl Attributes {
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         if is_relevant_item(cx, item) {
             inline_always::check(cx, item.span, item.ident.name, attrs);
         }
@@ -474,13 +474,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         if is_relevant_impl(cx, item) {
-            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
         if is_relevant_trait(cx, item) {
-            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 085ed9222c9..7c64bf46e7b 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -97,7 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR
 }
 
 fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
 
     find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC))
 }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 66a3e5e3d3c..8d9222e4bf6 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
             && let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
             && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
-            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && let attrs = cx.tcx.hir_attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
-            && cx.tcx.hir().attrs(impl_item_hir).is_empty()
+            && cx.tcx.hir_attrs(impl_item_hir).is_empty()
         {
             if adt_def.is_struct() {
                 check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index db3e6034c5b..2ae35b40055 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -384,7 +384,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
             .tcx
             .inherent_impls(def.did())
             .iter()
-            .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
+            .map(|imp_did| cx.tcx.hir_expect_item(imp_did.expect_local()))
             .any(|imp| has_unsafe(cx, imp))
     {
         span_lint_hir_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index e8638595c4b..e75abf28bac 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -25,7 +25,7 @@ pub fn check(
         && cx
             .tcx
             .hir_parent_iter(owner_id.into())
-            .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
+            .any(|(id, _node)| is_doc_hidden(cx.tcx.hir_attrs(id)))
     {
         return;
     }
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 33ba401d60c..9298f56b68b 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -163,7 +163,6 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
 
     fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
         if cmt.place.projections.is_empty() {
-            let map = &self.cx.tcx.hir();
             if is_argument(self.cx.tcx, cmt.hir_id) {
                 // Skip closure arguments
                 let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
@@ -174,7 +173,7 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
                 // skip if there is a `self` parameter binding to a type
                 // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
                 if let Some(trait_self_ty) = self.trait_self_ty {
-                    if map.name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
+                    if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
                         return;
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 9bf3baba4b5..591912cc8d5 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
             _ => return,
         };
         if cx.effective_visibilities.is_exported(item.owner_id.def_id)
-            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && let attrs = cx.tcx.hir_attrs(item.hir_id())
             && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
             && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
         {
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index ff75fcf2b41..5b42a40d850 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -209,9 +209,8 @@ impl FormatImplExpr<'_, '_> {
         // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
         // Since the argument to fmt is itself a reference: &self
         let reference = peel_ref_operators(self.cx, arg);
-        let map = self.cx.tcx.hir();
         // Is the reference self?
-        if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
+        if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
             let FormatTraitNames { name, .. } = self.format_trait_impl;
             span_lint(
                 self.cx,
diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
index 0bdb99d7b9a..8822b87f92f 100644
--- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
+++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
@@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
         let sm = cx.sess().source_map();
         let mut span = cx
             .tcx
-            .hir()
-            .attrs(item.hir_id())
+            .hir_attrs(item.hir_id())
             .iter()
             .filter(|i| i.is_doc_comment())
             .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index f1c9657f224..c3e0d5e8b69 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -21,7 +21,7 @@ use core::ops::ControlFlow;
 use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
     if let hir::ItemKind::Fn {
         ref sig,
@@ -51,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
     if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
@@ -74,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index 5b58113169b..e1dd7872b9d 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -182,7 +182,7 @@ fn suggestion<'tcx>(
 }
 
 fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span {
-    if let Some(attr) = tcx.hir().attrs(field.hir_id).first() {
+    if let Some(attr) = tcx.hir_attrs(field.hir_id).first() {
         field.span.with_lo(attr.span().lo())
     } else {
         field.span
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index 9b4a3b3f9c8..6a436fb4a9d 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -34,8 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
         if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
             && let Some(attr) = cx
                 .tcx
-                .hir()
-                .attrs(item.hir_id())
+                .hir_attrs(item.hir_id())
                 .iter()
                 .find(|a| a.has_name(sym::inline))
         {
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 20be22850b7..b712b351d06 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -98,7 +98,7 @@ impl LateLintPass<'_> for MacroUseImports {
         if cx.sess().opts.edition >= Edition::Edition2018
             && let hir::ItemKind::Use(path, _kind) = &item.kind
             && let hir_id = item.hir_id()
-            && let attrs = cx.tcx.hir().attrs(hir_id)
+            && let attrs = cx.tcx.hir_attrs(hir_id)
             && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
             && let Some(id) = path.res.iter().find_map(|res| match res {
                 Res::Def(DefKind::Mod, id) => Some(id),
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 496e0660d4f..64b07a5536b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -89,11 +89,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
         match item.kind {
             ItemKind::Enum(def, _) if def.variants.len() > 1 => {
                 let iter = def.variants.iter().filter_map(|v| {
-                    (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
+                    (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
                         .then_some((v.def_id, v.span))
                 });
                 if let Ok((id, span)) = iter.exactly_one()
-                    && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                    && !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
                 {
                     self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
                 }
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
                         "this seems like a manual implementation of the non-exhaustive pattern",
                         |diag| {
                             if let Some(non_exhaustive) =
-                                attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                                attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
                             {
                                 diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index d697f427c70..d29d1ea3e96 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>(
         cx,
         scrutinee,
         arms.iter()
-            .map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
+            .map(|arm| (cx.tcx.hir_attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
         e,
         false,
     )
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 41e4c75f843..250f17fa902 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                         HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
                     }
                     // the names technically don't have to match; this makes the lint more conservative
-                    && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
+                    && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
                     && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
                     && pat_contains_local(lhs.pat, a_id)
                     && pat_contains_local(rhs.pat, b_id)
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 1c64f78678a..7c190e123b7 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)))
 }
 
 /// 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/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 94d3657d9f1..7dde21d3edb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -4731,7 +4731,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         }
         let name = impl_item.ident.name.as_str();
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let item = cx.tcx.hir().expect_item(parent);
+        let item = cx.tcx.hir_expect_item(parent);
         let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
 
         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 47a9e17b3cf..3470c266c49 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
+        let attrs = cx.tcx.hir_attrs(hir::CRATE_HIR_ID);
         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
     }
 
@@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
         let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
 
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         if !is_from_proc_macro(cx, it) {
             self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
         }
@@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
         let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
 
-        let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(trait_item.hir_id());
         if !is_from_proc_macro(cx, trait_item) {
             self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
         }
@@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         }
 
         let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
-        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
         if !is_from_proc_macro(cx, impl_item) {
             self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
         }
@@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
         if !sf.is_positional() {
-            let attrs = cx.tcx.hir().attrs(sf.hir_id);
+            let attrs = cx.tcx.hir_attrs(sf.hir_id);
             if !is_from_proc_macro(cx, sf) {
                 self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
             }
@@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
-        let attrs = cx.tcx.hir().attrs(v.hir_id);
+        let attrs = cx.tcx.hir_attrs(v.hir_id);
         if !is_from_proc_macro(cx, v) {
             self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
         }
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 3cf1a80607e..2c578d81602 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
         match it.kind {
             hir::ItemKind::Fn { .. } => {
                 let desc = "a function";
-                let attrs = cx.tcx.hir().attrs(it.hir_id());
+                let attrs = cx.tcx.hir_attrs(it.hir_id());
                 check_missing_inline_attrs(cx, attrs, it.span, desc);
             },
             hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => {
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                                 // an impl is not provided
                                 let desc = "a default trait method";
                                 let item = cx.tcx.hir_trait_item(tit.id);
-                                let attrs = cx.tcx.hir().attrs(item.hir_id());
+                                let attrs = cx.tcx.hir_attrs(item.hir_id());
                                 check_missing_inline_attrs(cx, attrs, item.span, desc);
                             }
                         },
@@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
             }
         }
 
-        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
         check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index a7452c8a3c8..be728e6c8b7 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
                     self.cx,
                     MIXED_READ_WRITE_IN_EXPRESSION,
                     expr.span,
-                    format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
+                    format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
                     |diag| {
                         diag.span_note(
                             self.write_expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs
index 7eefb016aca..c90019f6ee1 100644
--- a/src/tools/clippy/clippy_lints/src/needless_if.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_if.rs
@@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf {
                 stmt.span,
                 "this `if` branch is empty",
                 "you can remove it",
-                if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() {
+                if cond.can_have_side_effects() || !cx.tcx.hir_attrs(stmt.hir_id).is_empty() {
                     // `{ foo }` or `{ foo } && bar` placed into a statement position would be
                     // interpreted as a block statement, force it to be an expression
                     if cond_snippet.starts_with('{') {
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 863a1f895c9..3efbed0c236 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -261,7 +261,7 @@ fn check<'tcx>(
     binding_id: HirId,
 ) -> Option<()> {
     let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
-    let binding_name = cx.tcx.hir().opt_name(binding_id)?;
+    let binding_name = cx.tcx.hir_opt_name(binding_id)?;
     let let_snippet = local_snippet_without_semicolon(cx, local)?;
 
     match usage.expr.kind {
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 dc10de24bc8..576bb27b254 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
@@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                     // We don't check unsafe functions.
                     return;
                 }
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
                     return;
                 }
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 dc85176ebb9..7bee89086b8 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
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 
         match kind {
             FnKind::ItemFn(.., header) => {
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
index 1baa3cb2f0f..fe8a02c64c6 100644
--- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -40,7 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
         if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind
             && !item.span.from_expansion()
         {
-            let attrs = cx.tcx.hir().attrs(item.hir_id());
+            let attrs = cx.tcx.hir_attrs(item.hir_id());
             let mut app = Applicability::MaybeIncorrect;
             let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app);
             for attr in attrs {
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index d4da12451f1..9b53608ae7f 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -351,7 +351,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Const(_, body_id) = &impl_item.kind {
             let item_def_id = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-            let item = cx.tcx.hir().expect_item(item_def_id);
+            let item = cx.tcx.hir_expect_item(item_def_id);
 
             match &item.kind {
                 ItemKind::Impl(Impl {
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index c3c09946c27..378fed481f4 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -181,7 +181,7 @@ fn in_impl<'tcx>(
 ) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
     if let Some(block) = get_enclosing_block(cx, e.hir_id)
         && let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id())
-        && let item = cx.tcx.hir().expect_item(impl_def_id.expect_local())
+        && let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
         && let ItemKind::Impl(item) = &item.kind
         && let Some(of_trait) = &item.of_trait
         && let Some(seg) = of_trait.path.segments.last()
@@ -200,7 +200,7 @@ fn in_impl<'tcx>(
 fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
     if let ty::Adt(adt_def, _) = middle_ty.kind()
         && let Some(local_did) = adt_def.did().as_local()
-        && let item = cx.tcx.hir().expect_item(local_did)
+        && let item = cx.tcx.hir_expect_item(local_did)
         && let middle_ty_id = item.owner_id.to_def_id()
         && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
         && let Res::Def(_, hir_ty_id) = path.res
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 49bc5608346..320c0286bb7 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
                 if header.abi != ExternAbi::Rust {
                     return;
                 }
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 for a in attrs {
                     if let Some(meta_items) = a.meta_item_list() {
                         if a.has_name(sym::proc_macro_derive)
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index db03657c9af..fd21893232d 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
             // Only pertains to fields that start with an underscore, and are public.
             if field.ident.as_str().starts_with('_') && is_visible(field)
                 // We ignore fields that have `#[doc(hidden)]`.
-                && !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id))
+                && !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id))
                 // We ignore fields that are `PhantomData`.
                 && !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
             {
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 6bd68dd4109..49b522994fb 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                             },
                         ),
                         VecInitKind::WithExprCapacity(hir_id) => {
-                            let e = cx.tcx.hir().expect_expr(hir_id);
+                            let e = cx.tcx.hir_expect_expr(hir_id);
                             span_lint_hir_and_then(
                                 cx,
                                 READ_ZERO_BYTE_VEC,
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index 5a25483c397..07ae92fa984 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
         // We only show this warning for public exported methods.
         && cx.effective_visibilities.is_exported(fn_def)
         // We don't want to emit this lint if the `#[must_use]` attribute is already there.
-        && !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
+        && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
         && cx.tcx.visibility(fn_def.to_def_id()).is_public()
         && let ret_ty = return_ty(cx, owner_id)
         && let self_arg = nth_arg(cx, owner_id, 0)
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 3ba6d628459..4cb73df8b48 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
             && let Some(stmt) = block.stmts.iter().last()
             && let StmtKind::Let(local) = &stmt.kind
             && local.ty.is_none()
-            && cx.tcx.hir().attrs(local.hir_id).is_empty()
+            && cx.tcx.hir_attrs(local.hir_id).is_empty()
             && let Some(initexpr) = &local.init
             && let PatKind::Binding(_, local_id, _, _) = local.pat.kind
             && path_to_local_id(retexpr, local_id)
@@ -401,7 +401,7 @@ fn check_final_expr<'tcx>(
             // This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
             // `#[expect(clippy::needless_return)]` needs to be handled separately to
             // actually fulfill the expectation (clippy::#12998)
-            match cx.tcx.hir().attrs(expr.hir_id) {
+            match cx.tcx.hir_attrs(expr.hir_id) {
                 [] => {},
                 [attr] => {
                     if matches!(Level::from_attr(attr), Some(Level::Expect(_)))
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
index fc02c3a5171..8b2d597b9e3 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
         }
 
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let item = cx.tcx.hir().expect_item(parent);
+        let item = cx.tcx.hir_expect_item(parent);
         let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
         let ret_ty = return_ty(cx, impl_item.owner_id);
 
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 746bf018bcc..be533ca915e 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -429,8 +429,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
 fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
     span.to(cx
         .tcx
-        .hir()
-        .attrs(hir_id)
+        .hir_attrs(hir_id)
         .iter()
         .fold(span, |acc, attr| acc.to(attr.span())))
 }
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 2c6c7569316..582aa6e6001 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             return;
         }
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let parent_item = cx.tcx.hir().expect_item(parent);
+        let parent_item = cx.tcx.hir_expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
         let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
             clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 6f6683eb971..b466a8e127a 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -318,7 +318,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
             {
                 if call_to_unwrap == unwrappable.safe_to_unwrap {
                     let is_entire_condition = unwrappable.is_entire_condition;
-                    let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
+                    let unwrappable_variable_name = self.cx.tcx.hir_name(unwrappable.local_id);
                     let suggested_pattern = if call_to_unwrap {
                         unwrappable.kind.success_variant_pattern()
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 9d8c161873c..4309cd2c9ab 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -793,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
 }
 
 fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
     get_attr(cx.sess(), attrs, "author").count() > 0
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
index b108951978f..9910be9bc28 100644
--- a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
@@ -59,6 +59,6 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
 }
 
 fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
     get_attr(cx.sess(), attrs, "dump").count() > 0
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 89b4c48b8b1..16d51fa0902 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -247,7 +247,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
 /// This function extracts the version value of a `clippy::version` attribute if the given value has
 /// one
 pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     attrs.iter().find_map(|attr| {
         if let hir::Attribute::Unparsed(attr_kind) = &attr
             // Identify attribute
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index d8969246844..80613a51c14 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2036,15 +2036,14 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
 }
 
 pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..))
+    find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr(..))
 }
 
 pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
-    let map = &tcx.hir();
     let mut prev_enclosing_node = None;
     let mut enclosing_node = node;
     while Some(enclosing_node) != prev_enclosing_node {
-        if has_attr(map.attrs(enclosing_node), symbol) {
+        if has_attr(tcx.hir_attrs(enclosing_node), symbol) {
             return true;
         }
         prev_enclosing_node = Some(enclosing_node);
@@ -2061,7 +2060,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
         .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
         .any(|(id, _)| {
             has_attr(
-                tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
+                tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)),
                 sym::automatically_derived,
             )
         })
@@ -2344,16 +2343,14 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
 
 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
     cx.tcx
-        .hir()
-        .attrs(hir::CRATE_HIR_ID)
+        .hir_attrs(hir::CRATE_HIR_ID)
         .iter()
         .any(|attr| attr.name_or_empty() == sym::no_std)
 }
 
 pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
     cx.tcx
-        .hir()
-        .attrs(hir::CRATE_HIR_ID)
+        .hir_attrs(hir::CRATE_HIR_ID)
         .iter()
         .any(|attr| attr.name_or_empty() == sym::no_core)
 }
@@ -2643,8 +2640,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
                         // We could also check for the type name `test::TestDescAndFn`
                         if let Res::Def(DefKind::Struct, _) = path.res {
                             let has_test_marker = tcx
-                                .hir()
-                                .attrs(item.hir_id())
+                                .hir_attrs(item.hir_id())
                                 .iter()
                                 .any(|a| a.has_name(sym::rustc_test_marker));
                             if has_test_marker {
@@ -2688,7 +2684,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
 /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
 /// use [`is_in_cfg_test`]
 pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
-    tcx.hir().attrs(id).iter().any(|attr| {
+    tcx.hir_attrs(id).iter().any(|attr| {
         if attr.has_name(sym::cfg)
             && let Some(items) = attr.meta_item_list()
             && let [item] = &*items
@@ -2713,12 +2709,10 @@ 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 {
-    let hir = tcx.hir();
-
     tcx.has_attr(def_id, sym::cfg)
         || tcx
             .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
-            .flat_map(|(parent_id, _)| hir.attrs(parent_id))
+            .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
             .any(|attr| attr.has_name(sym::cfg))
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 5bb2b12988a..0316de172de 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -108,7 +108,7 @@ impl Msrv {
             let start = cx.last_node_with_lint_attrs;
             if let Some(msrv_attr) = once(start)
                 .chain(cx.tcx.hir_parent_id_iter(start))
-                .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id)))
+                .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir_attrs(id)))
             {
                 return Some(msrv_attr);
             }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 24b4f0d9e6d..9cc66593dcc 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -847,7 +847,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
             let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
 
             // identifier referring to the variable currently triggered (i.e.: `fp`)
-            let ident_str = map.name(id).to_string();
+            let ident_str = self.cx.tcx.hir_name(id).to_string();
             // full identifier that includes projection (i.e.: `fp.field`)
             let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
 
@@ -876,7 +876,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
                         ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
-                            let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
+                            let expr = self.cx.tcx.hir_expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
                             if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 978836cb663..08d3c1c343e 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -481,9 +481,17 @@ impl Config {
     }
 
     pub fn has_asm_support(&self) -> bool {
+        // This should match the stable list in `LoweringContext::lower_inline_asm`.
         static ASM_SUPPORTED_ARCHS: &[&str] = &[
-            "x86", "x86_64", "arm", "aarch64", "riscv32",
+            "x86",
+            "x86_64",
+            "arm",
+            "aarch64",
+            "arm64ec",
+            "riscv32",
             "riscv64",
+            "loongarch64",
+            "s390x",
             // These targets require an additional asm_experimental_arch feature.
             // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32",
         ];
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 5d257029a46..0a2d3ac63a7 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -377,7 +377,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn get_global_alloc_bytes(
         &self,
         id: AllocId,
-        kind: MemoryKind,
         bytes: &[u8],
         align: Align,
     ) -> InterpResult<'tcx, MiriAllocBytes> {
@@ -386,7 +385,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
             // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
             // this function gets called before the first time `addr_from_alloc_id` gets called.
-            this.addr_from_alloc_id(id, kind)?;
+            this.addr_from_alloc_id(id, MiriMemoryKind::Global.into())?;
             // The memory we need here will have already been allocated during an earlier call to
             // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
             // fetch the previously prepared bytes from `prepared_alloc_bytes`.
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index dbb092f6728..90beffbf830 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -814,6 +814,59 @@ impl<'tcx> MiriMachine<'tcx> {
             .and_then(|(_allocated, deallocated)| *deallocated)
             .map(Span::data)
     }
+
+    fn init_allocation(
+        ecx: &MiriInterpCx<'tcx>,
+        id: AllocId,
+        kind: MemoryKind,
+        size: Size,
+        align: Align,
+    ) -> InterpResult<'tcx, AllocExtra<'tcx>> {
+        if ecx.machine.tracked_alloc_ids.contains(&id) {
+            ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id, size, align, kind));
+        }
+
+        let borrow_tracker = ecx
+            .machine
+            .borrow_tracker
+            .as_ref()
+            .map(|bt| bt.borrow_mut().new_allocation(id, size, kind, &ecx.machine));
+
+        let data_race = ecx.machine.data_race.as_ref().map(|data_race| {
+            data_race::AllocState::new_allocation(
+                data_race,
+                &ecx.machine.threads,
+                size,
+                kind,
+                ecx.machine.current_span(),
+            )
+        });
+        let weak_memory = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);
+
+        // If an allocation is leaked, we want to report a backtrace to indicate where it was
+        // allocated. We don't need to record a backtrace for allocations which are allowed to
+        // leak.
+        let backtrace = if kind.may_leak() || !ecx.machine.collect_leak_backtraces {
+            None
+        } else {
+            Some(ecx.generate_stacktrace())
+        };
+
+        if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) {
+            ecx.machine
+                .allocation_spans
+                .borrow_mut()
+                .insert(id, (ecx.machine.current_span(), None));
+        }
+
+        interp_ok(AllocExtra {
+            borrow_tracker,
+            data_race,
+            weak_memory,
+            backtrace,
+            sync: FxHashMap::default(),
+        })
+    }
 }
 
 impl VisitProvenance for MiriMachine<'_> {
@@ -1200,57 +1253,15 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         }
     }
 
-    fn init_alloc_extra(
+    fn init_local_allocation(
         ecx: &MiriInterpCx<'tcx>,
         id: AllocId,
         kind: MemoryKind,
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Self::AllocExtra> {
-        if ecx.machine.tracked_alloc_ids.contains(&id) {
-            ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id, size, align, kind));
-        }
-
-        let borrow_tracker = ecx
-            .machine
-            .borrow_tracker
-            .as_ref()
-            .map(|bt| bt.borrow_mut().new_allocation(id, size, kind, &ecx.machine));
-
-        let data_race = ecx.machine.data_race.as_ref().map(|data_race| {
-            data_race::AllocState::new_allocation(
-                data_race,
-                &ecx.machine.threads,
-                size,
-                kind,
-                ecx.machine.current_span(),
-            )
-        });
-        let weak_memory = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);
-
-        // If an allocation is leaked, we want to report a backtrace to indicate where it was
-        // allocated. We don't need to record a backtrace for allocations which are allowed to
-        // leak.
-        let backtrace = if kind.may_leak() || !ecx.machine.collect_leak_backtraces {
-            None
-        } else {
-            Some(ecx.generate_stacktrace())
-        };
-
-        if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) {
-            ecx.machine
-                .allocation_spans
-                .borrow_mut()
-                .insert(id, (ecx.machine.current_span(), None));
-        }
-
-        interp_ok(AllocExtra {
-            borrow_tracker,
-            data_race,
-            weak_memory,
-            backtrace,
-            sync: FxHashMap::default(),
-        })
+        assert!(kind != MiriMemoryKind::Global.into());
+        MiriMachine::init_allocation(ecx, id, kind, size, align)
     }
 
     fn adjust_alloc_root_pointer(
@@ -1340,13 +1351,13 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         alloc: &'b Allocation,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
     {
-        let kind = Self::GLOBAL_KIND.unwrap().into();
         let alloc = alloc.adjust_from_tcx(
             &ecx.tcx,
-            |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align),
+            |bytes, align| ecx.get_global_alloc_bytes(id, bytes, align),
             |ptr| ecx.global_root_pointer(ptr),
         )?;
-        let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
+        let kind = MiriMemoryKind::Global.into();
+        let extra = MiriMachine::init_allocation(ecx, id, kind, alloc.size(), alloc.align)?;
         interp_ok(Cow::Owned(alloc.with_extra(extra)))
     }
 
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
index 791ffa7343d..e6282613df7 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
+++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize);
+unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
 fn main() {
     let mut data = [0u8; 16];
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
index 9a82c69fba8..ded9d0b669e 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
+++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize);
+unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
 fn main() {
     let mut data = [0u16; 8];
diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
index e42811d9e13..f73c1b6acb7 100644
--- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
@@ -2,7 +2,7 @@
 
 mod rusti {
     #[rustc_intrinsic]
-    pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
+    pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
 }
 
 pub fn main() {
diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
index e046a30e734..a41cb8b1553 100644
--- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
@@ -2,7 +2,7 @@
 
 mod rusti {
     #[rustc_intrinsic]
-    pub unsafe fn cttz_nonzero<T>(_x: T) -> u32;
+    pub unsafe fn cttz_nonzero<T>(x: T) -> u32;
 }
 
 pub fn main() {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
index d75046ff360..7ee0117ffb3 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
index 8d343cdc1bd..22bf881cef0 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
index 737a6fbafe0..571121f4019 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
index ee8b45c0aae..12600ef6125 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
index 4bb5ded1033..f848a137c27 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
index 6b42ae56ece..43ef4a95738 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
index 81019a1c608..83432c2b77c 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
index 24896bcae51..609443e6d4e 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
index fbb67d28fed..fb3eb11c0bb 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
index 93236bf4874..b46c4777ba7 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
index 2770dea4406..8a3b9dbdc71 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
index 1272566c07c..e0c826cb046 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
index a1165794982..c7c5bf40226 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
index 0e68f4eaff7..fb3d7bda4e4 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
index ad3ac16dc6f..2cf27b33553 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
index 1addb9fb1d7..22dca505e64 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
index a04c29c37da..b59c8fa8e0c 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
index 32bdcd07073..4ad0cd343a4 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
index 861af44a66f..fd47dfc03d7 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
index 3b3e208f32f..680ebda1c96 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
index 81ca766de47..e4cb36c5d2e 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
index 2b437f38552..fe4bac92bd3 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
index 94ee572f4d0..219efd80316 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
@@ -2,7 +2,7 @@
 
 // Directly call intrinsic to avoid debug assertions in libstd
 #[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
+unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
index f043bb7ce9f..cc753dac215 100644
--- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
@@ -16,7 +16,7 @@ use std::simd::prelude::*;
 
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn simd_shuffle_const_generic<T, U, const IDX: &'static [u32]>(_x: T, _y: T) -> U;
+pub unsafe fn simd_shuffle_const_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
 
 fn simd_ops_f32() {
     let a = f32x4::splat(10.0);
diff --git a/src/tools/rls/Cargo.toml b/src/tools/rls/Cargo.toml
deleted file mode 100644
index b7aa659c25a..00000000000
--- a/src/tools/rls/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "rls"
-version = "2.0.0"
-edition = "2021"
-license = "Apache-2.0/MIT"
-
-[dependencies]
-serde_json = "1.0.83"
diff --git a/src/tools/rls/README.md b/src/tools/rls/README.md
deleted file mode 100644
index 43c331c413f..00000000000
--- a/src/tools/rls/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# RLS Stub
-
-RLS has been replaced with [rust-analyzer](https://rust-analyzer.github.io/).
-
-This directory contains a stub which replaces RLS with a simple LSP server
-which only displays an alert to the user that RLS is no longer available.
diff --git a/src/tools/rls/src/main.rs b/src/tools/rls/src/main.rs
deleted file mode 100644
index 3a95b47cd4d..00000000000
--- a/src/tools/rls/src/main.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! RLS stub.
-//!
-//! This is a small stub that replaces RLS to alert the user that RLS is no
-//! longer available.
-
-use std::error::Error;
-use std::io::{BufRead, Write};
-
-use serde_json::Value;
-
-const ALERT_MSG: &str = "\
-RLS is no longer available as of Rust 1.65.
-Consider migrating to rust-analyzer instead.
-See https://rust-analyzer.github.io/ for installation instructions.
-";
-
-fn main() {
-    if let Err(e) = run() {
-        eprintln!("error: {e}");
-        std::process::exit(1);
-    }
-}
-
-struct Message {
-    method: Option<String>,
-}
-
-fn run() -> Result<(), Box<dyn Error>> {
-    let mut stdin = std::io::stdin().lock();
-    let mut stdout = std::io::stdout().lock();
-
-    let init = read_message(&mut stdin)?;
-    if init.method.as_deref() != Some("initialize") {
-        return Err(format!("expected initialize, got {:?}", init.method).into());
-    }
-    // No response, the LSP specification says that `showMessageRequest` may
-    // be posted before during this phase.
-
-    // message_type 1 is "Error"
-    let alert = serde_json::json!({
-        "jsonrpc": "2.0",
-        "id": 1,
-        "method": "window/showMessageRequest",
-        "params": {
-            "message_type": "1",
-            "message": ALERT_MSG
-        }
-    });
-    write_message_raw(&mut stdout, serde_json::to_string(&alert).unwrap())?;
-
-    loop {
-        let message = read_message(&mut stdin)?;
-        if message.method.as_deref() == Some("shutdown") {
-            std::process::exit(0);
-        }
-    }
-}
-
-fn read_message_raw<R: BufRead>(reader: &mut R) -> Result<String, Box<dyn Error>> {
-    let mut content_length: usize = 0;
-
-    // Read headers.
-    loop {
-        let mut line = String::new();
-        reader.read_line(&mut line)?;
-        if line.is_empty() {
-            return Err("remote disconnected".into());
-        }
-        if line == "\r\n" {
-            break;
-        }
-        if line.to_lowercase().starts_with("content-length:") {
-            let value = &line[15..].trim();
-            content_length = usize::from_str_radix(value, 10)?;
-        }
-    }
-    if content_length == 0 {
-        return Err("no content-length".into());
-    }
-
-    let mut buffer = vec![0; content_length];
-    reader.read_exact(&mut buffer)?;
-    let content = String::from_utf8(buffer)?;
-
-    Ok(content)
-}
-
-fn read_message<R: BufRead>(reader: &mut R) -> Result<Message, Box<dyn Error>> {
-    let m = read_message_raw(reader)?;
-    match serde_json::from_str::<Value>(&m) {
-        Ok(message) => Ok(Message {
-            method: message.get("method").and_then(|value| value.as_str().map(String::from)),
-        }),
-        Err(e) => Err(format!("failed to parse message {m}\n{e}").into()),
-    }
-}
-
-fn write_message_raw<W: Write>(mut writer: W, output: String) -> Result<(), Box<dyn Error>> {
-    write!(writer, "Content-Length: {}\r\n\r\n{}", output.len(), output)?;
-    writer.flush()?;
-    Ok(())
-}
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index ddcf315a267..e54747c129a 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -553,6 +553,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
 name = "html5ever"
 version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -874,9 +880,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.45"
+version = "0.4.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b07d36d96ffe1b5b16ddf2bc80b3b26bb7a498b2a6591061250bf0af8e8095ad"
+checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -886,6 +892,7 @@ dependencies = [
  "elasticlunr-rs",
  "env_logger",
  "handlebars",
+ "hex",
  "log",
  "memchr",
  "once_cell",
@@ -894,6 +901,7 @@ dependencies = [
  "regex",
  "serde",
  "serde_json",
+ "sha2",
  "shlex",
  "tempfile",
  "toml 0.5.11",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 6aec0bec0fa..831233e3065 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.45"
+version = "0.4.47"
 default-features = false
 features = ["search"]
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index 33f2a51215d..4b510e308c9 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -151,6 +151,7 @@ fn get_book_dir(args: &ArgMatches) -> PathBuf {
 fn load_book(book_dir: &Path) -> Result3<MDBook> {
     let mut book = MDBook::load(book_dir)?;
     book.config.set("output.html.input-404", "").unwrap();
+    book.config.set("output.html.hash-files", true).unwrap();
     Ok(book)
 }
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 569d3c67b04..81c55ecaa7a 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -81,7 +81,6 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>,
     ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
     ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
     ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
-    ("src/tools/x", &[], None, &[]),
     // tidy-alphabetical-end
 ];
 
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index bc3519142dd..4078d462f55 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -29,6 +29,7 @@ fn main() {
         FromStr::from_str(&env::args().nth(4).expect("need concurrency"))
             .expect("concurrency must be a number");
 
+    let root_manifest = root_path.join("Cargo.toml");
     let src_path = root_path.join("src");
     let tests_path = root_path.join("tests");
     let library_path = root_path.join("library");
@@ -137,6 +138,7 @@ fn main() {
         check!(edition, &compiler_path);
         check!(edition, &library_path);
 
+        check!(alphabetical, &root_manifest);
         check!(alphabetical, &src_path);
         check!(alphabetical, &tests_path);
         check!(alphabetical, &compiler_path);
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index edf7658d25f..08ee5c16c12 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -32,8 +32,6 @@ pub fn filter_dirs(path: &Path) -> bool {
         "src/doc/rustc-dev-guide",
         "src/doc/reference",
         "src/gcc",
-        // Filter RLS output directories
-        "target/rls",
         "src/bootstrap/target",
         "vendor",
     ];
diff --git a/src/tools/x/Cargo.lock b/src/tools/x/Cargo.lock
deleted file mode 100644
index 09e5c750749..00000000000
--- a/src/tools/x/Cargo.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "x"
-version = "0.1.1"
diff --git a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs b/tests/assembly/naked-functions/aarch64-naked-fn-no-bti-prolog.rs
index 46e627eaa00..46e627eaa00 100644
--- a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs
+++ b/tests/assembly/naked-functions/aarch64-naked-fn-no-bti-prolog.rs
diff --git a/tests/assembly/naked-functions/aix.rs b/tests/assembly/naked-functions/aix.rs
new file mode 100644
index 00000000000..cc0825b3738
--- /dev/null
+++ b/tests/assembly/naked-functions/aix.rs
@@ -0,0 +1,35 @@
+//@ revisions: elfv1-be aix
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//
+//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[elfv1-be] needs-llvm-components: powerpc
+//
+//@[aix] compile-flags: --target powerpc64-ibm-aix
+//@[aix] needs-llvm-components: powerpc
+
+#![crate_type = "lib"]
+#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)]
+#![no_core]
+
+// tests that naked functions work for the `powerpc64-ibm-aix` target.
+//
+// This target is special because it uses the XCOFF binary format
+// It is tested alongside an elf powerpc target to pin down commonalities and differences.
+//
+// https://doc.rust-lang.org/rustc/platform-support/aix.html
+// https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format
+
+extern crate minicore;
+use minicore::*;
+
+// elfv1-be: .p2align 2
+// aix: .align 2
+// CHECK: .globl blr
+// CHECK-LABEL: blr:
+// CHECK: blr
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn blr() {
+    naked_asm!("blr")
+}
diff --git a/tests/assembly/wasm32-naked-fn.rs b/tests/assembly/naked-functions/wasm32.rs
index 4911a6bd08f..4911a6bd08f 100644
--- a/tests/assembly/wasm32-naked-fn.rs
+++ b/tests/assembly/naked-functions/wasm32.rs
diff --git a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs b/tests/assembly/naked-functions/x86_64-naked-fn-no-cet-prolog.rs
index 54e1d93c68b..54e1d93c68b 100644
--- a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs
+++ b/tests/assembly/naked-functions/x86_64-naked-fn-no-cet-prolog.rs
diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs
index e5978bfc761..c1f208d7909 100644
--- a/tests/codegen/enum/enum-two-variants-match.rs
+++ b/tests/codegen/enum/enum-two-variants-match.rs
@@ -7,19 +7,22 @@
 // CHECK-LABEL: @option_match
 #[no_mangle]
 pub fn option_match(x: Option<i32>) -> u16 {
-    // CHECK: %x = alloca [8 x i8]
-    // CHECK: store i32 %0, ptr %x
-    // CHECK: %[[TAG:.+]] = load i32, ptr %x
-    // CHECK-SAME: !range ![[ZERO_ONE_32:[0-9]+]]
-    // CHECK: %[[DISCR:.+]] = zext i32 %[[TAG]] to i64
+    // CHECK-NOT: %x = alloca
+    // CHECK: %[[OUT:.+]] = alloca [2 x i8]
+    // CHECK-NOT: %x = alloca
+
+    // CHECK: %[[DISCR:.+]] = zext i32 %x.0 to i64
     // CHECK: %[[COND:.+]] = trunc nuw i64 %[[DISCR]] to i1
     // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]]
 
     // CHECK: [[TRUE]]:
-    // CHECK: store i16 13
+    // CHECK: store i16 13, ptr %[[OUT]]
 
     // CHECK: [[FALSE]]:
-    // CHECK: store i16 42
+    // CHECK: store i16 42, ptr %[[OUT]]
+
+    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
+    // CHECK: ret i16 %[[RET]]
     match x {
         Some(_) => 13,
         None => 42,
@@ -29,23 +32,23 @@ pub fn option_match(x: Option<i32>) -> u16 {
 // CHECK-LABEL: @result_match
 #[no_mangle]
 pub fn result_match(x: Result<u64, i64>) -> u16 {
-    // CHECK: %x = alloca [16 x i8]
-    // CHECK: store i64 %0, ptr %x
-    // CHECK: %[[DISCR:.+]] = load i64, ptr %x
-    // CHECK-SAME: !range ![[ZERO_ONE_64:[0-9]+]]
-    // CHECK: %[[COND:.+]] = trunc nuw i64 %[[DISCR]] to i1
+    // CHECK-NOT: %x = alloca
+    // CHECK: %[[OUT:.+]] = alloca [2 x i8]
+    // CHECK-NOT: %x = alloca
+
+    // CHECK: %[[COND:.+]] = trunc nuw i64 %x.0 to i1
     // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]]
 
     // CHECK: [[TRUE]]:
-    // CHECK: store i16 13
+    // CHECK: store i16 13, ptr %[[OUT]]
 
     // CHECK: [[FALSE]]:
-    // CHECK: store i16 42
+    // CHECK: store i16 42, ptr %[[OUT]]
+
+    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
+    // CHECK: ret i16 %[[RET]]
     match x {
         Err(_) => 13,
         Ok(_) => 42,
     }
 }
-
-// CHECK: ![[ZERO_ONE_32]] = !{i32 0, i32 2}
-// CHECK: ![[ZERO_ONE_64]] = !{i64 0, i64 2}
diff --git a/tests/codegen/intrinsics/cold_path2.rs b/tests/codegen/intrinsics/cold_path2.rs
index 54ee473e620..0891c878fd9 100644
--- a/tests/codegen/intrinsics/cold_path2.rs
+++ b/tests/codegen/intrinsics/cold_path2.rs
@@ -25,8 +25,8 @@ pub fn test(x: Option<bool>) {
         path_b();
     }
 
-    // CHECK-LABEL: @test(
-    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %0, 2
+    // CHECK-LABEL: void @test(i8{{.+}}%x)
+    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %x, 2
     // CHECK: br i1 %[[IS_NONE]], label %bb2, label %bb1, !prof ![[NUM:[0-9]+]]
     // CHECK: bb1:
     // CHECK: path_a
diff --git a/tests/codegen/match-optimizes-away.rs b/tests/codegen/match-optimizes-away.rs
index 8a70d993423..5e9be72a09f 100644
--- a/tests/codegen/match-optimizes-away.rs
+++ b/tests/codegen/match-optimizes-away.rs
@@ -1,5 +1,4 @@
-//
-//@ compile-flags: -Copt-level=3
+//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
 #![crate_type = "lib"]
 
 pub enum Three {
@@ -18,9 +17,9 @@ pub enum Four {
 
 #[no_mangle]
 pub fn three_valued(x: Three) -> Three {
-    // CHECK-LABEL: @three_valued
+    // CHECK-LABEL: i8 @three_valued(i8{{.+}}%x)
     // CHECK-NEXT: {{^.*:$}}
-    // CHECK-NEXT: ret i8 %0
+    // CHECK-NEXT: ret i8 %x
     match x {
         Three::A => Three::A,
         Three::B => Three::B,
@@ -30,9 +29,9 @@ pub fn three_valued(x: Three) -> Three {
 
 #[no_mangle]
 pub fn four_valued(x: Four) -> Four {
-    // CHECK-LABEL: @four_valued
+    // CHECK-LABEL: i16 @four_valued(i16{{.+}}%x)
     // CHECK-NEXT: {{^.*:$}}
-    // CHECK-NEXT: ret i16 %0
+    // CHECK-NEXT: ret i16 %x
     match x {
         Four::A => Four::A,
         Four::B => Four::B,
diff --git a/tests/codegen/naked-fn/naked-functions.rs b/tests/codegen/naked-fn/naked-functions.rs
index 6483e27c97a..3fe795178b7 100644
--- a/tests/codegen/naked-fn/naked-functions.rs
+++ b/tests/codegen/naked-fn/naked-functions.rs
@@ -1,10 +1,12 @@
 //@ add-core-stubs
-//@ revisions: linux win macos thumb
+//@ revisions: linux win_x86 win_i686 macos thumb
 //
 //@[linux] compile-flags: --target x86_64-unknown-linux-gnu
 //@[linux] needs-llvm-components: x86
-//@[win] compile-flags: --target x86_64-pc-windows-gnu
-//@[win] needs-llvm-components: x86
+//@[win_x86] compile-flags: --target x86_64-pc-windows-gnu
+//@[win_x86] needs-llvm-components: x86
+//@[win_i686] compile-flags: --target i686-pc-windows-gnu
+//@[win_i686] needs-llvm-components: x86
 //@[macos] compile-flags: --target aarch64-apple-darwin
 //@[macos] needs-llvm-components: arm
 //@[thumb] compile-flags: --target thumbv7em-none-eabi
@@ -19,10 +21,11 @@ use minicore::*;
 
 // linux,win: .intel_syntax
 //
-// linux:   .pushsection .text.naked_empty,\22ax\22, @progbits
-// macos:   .pushsection __TEXT,__text,regular,pure_instructions
-// win: .pushsection .text.naked_empty,\22xr\22
-// thumb:   .pushsection .text.naked_empty,\22ax\22, %progbits
+// linux:    .pushsection .text.naked_empty,\22ax\22, @progbits
+// macos:    .pushsection __TEXT,__text,regular,pure_instructions
+// win_x86:  .pushsection .text.naked_empty,\22xr\22
+// win_i686: .pushsection .text._naked_empty,\22xr\22
+// thumb:    .pushsection .text.naked_empty,\22ax\22, %progbits
 //
 // CHECK: .balign 4
 //
@@ -34,10 +37,12 @@ use minicore::*;
 //
 // linux: .type naked_empty, @function
 //
-// win: .def naked_empty
-// win: .scl 2
-// win: .type 32
-// win: .endef naked_empty
+// win_x86:  .def naked_empty
+// win_i686: .def _naked_empty
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
 //
 // thumb: .type naked_empty, %function
 // thumb: .thumb
@@ -66,10 +71,11 @@ pub unsafe extern "C" fn naked_empty() {
 
 // linux,win: .intel_syntax
 //
-// linux:   .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits
-// macos:   .pushsection __TEXT,__text,regular,pure_instructions
-// win: .pushsection .text.naked_with_args_and_return,\22xr\22
-// thumb:   .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits
+// linux:    .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits
+// macos:    .pushsection __TEXT,__text,regular,pure_instructions
+// win_x86:  .pushsection .text.naked_with_args_and_return,\22xr\22
+// win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22
+// thumb:    .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits
 //
 // CHECK: .balign 4
 //
@@ -81,10 +87,12 @@ pub unsafe extern "C" fn naked_empty() {
 //
 // linux: .type naked_with_args_and_return, @function
 //
-// win: .def naked_with_args_and_return
-// win: .scl 2
-// win: .type 32
-// win: .endef naked_with_args_and_return
+// win_x86:  .def naked_with_args_and_return
+// win_i686: .def _naked_with_args_and_return
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
 //
 // thumb: .type naked_with_args_and_return, %function
 // thumb: .thumb
@@ -92,7 +100,7 @@ pub unsafe extern "C" fn naked_empty() {
 //
 // CHECK-LABEL: naked_with_args_and_return:
 //
-// linux, win: lea rax, [rdi + rsi]
+// linux, win_x86,win_i686: lea rax, [rdi + rsi]
 // macos: add x0, x0, x1
 // thumb: adds r0, r0, r1
 //
@@ -124,10 +132,10 @@ pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize
     }
 }
 
-// linux:   .pushsection .text.some_different_name,\22ax\22, @progbits
-// macos:   .pushsection .text.some_different_name,regular,pure_instructions
-// win: .pushsection .text.some_different_name,\22xr\22
-// thumb:   .pushsection .text.some_different_name,\22ax\22, %progbits
+// linux:            .pushsection .text.some_different_name,\22ax\22, @progbits
+// macos:            .pushsection .text.some_different_name,regular,pure_instructions
+// win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22
+// thumb:            .pushsection .text.some_different_name,\22ax\22, %progbits
 // CHECK-LABEL: test_link_section:
 #[no_mangle]
 #[naked]
@@ -139,3 +147,19 @@ pub unsafe extern "C" fn test_link_section() {
     #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
     naked_asm!("bx lr");
 }
+
+// win_x86:  .def fastcall_cc
+// win_i686: .def @fastcall_cc@4
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
+//
+// win_x86-LABEL: fastcall_cc:
+// win_i686-LABEL: @fastcall_cc@4:
+#[cfg(target_os = "windows")]
+#[no_mangle]
+#[naked]
+pub unsafe extern "fastcall" fn fastcall_cc(x: i32) -> i32 {
+    naked_asm!("ret");
+}
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
index ca15e510173..23a084c51f4 100644
--- a/tests/codegen/try_question_mark_nop.rs
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -17,10 +17,10 @@ use std::ptr::NonNull;
 pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> {
     // CHECK: start:
     // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1
-    // TWENTY-NEXT: %.2 = select i1 %[[IS_SOME]], i32 %1, i32 undef
+    // TWENTY-NEXT: %[[PAYLOAD:.+]] = select i1 %[[IS_SOME]], i32 %1, i32 undef
     // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0
     // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1
-    // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %.2, 1
+    // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %[[PAYLOAD]], 1
     // CHECK-NEXT: ret { i32, i32 } [[REG2]]
     match x {
         Some(x) => Some(x),
@@ -33,7 +33,7 @@ pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> {
 pub fn option_nop_traits_32(x: Option<u32>) -> Option<u32> {
     // CHECK: start:
     // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1
-    // TWENTY-NEXT: %.1 = select i1 %[[IS_SOME]], i32 %1, i32 undef
+    // TWENTY-NEXT: select i1 %[[IS_SOME]], i32 %1, i32 undef
     // CHECK-NEXT: insertvalue { i32, i32 }
     // CHECK-NEXT: insertvalue { i32, i32 }
     // CHECK-NEXT: ret { i32, i32 }
diff --git a/tests/mir-opt/global_asm.rs b/tests/mir-opt/global_asm.rs
new file mode 100644
index 00000000000..22b782d365e
--- /dev/null
+++ b/tests/mir-opt/global_asm.rs
@@ -0,0 +1,9 @@
+// skip-filecheck
+//@ needs-asm-support
+
+// `global_asm!` gets a fake body, make sure it is handled correctly
+
+// EMIT_MIR global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
+core::arch::global_asm!("/* */");
+
+fn main() {}
diff --git a/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir b/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
new file mode 100644
index 00000000000..cec3c4a8261
--- /dev/null
+++ b/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
@@ -0,0 +1,9 @@
+// MIR for `{global_asm#0}` after SimplifyLocals-final
+
+{global_asm#0}: ! = {
+    let mut _0: !;
+
+    bb0: {
+        asm!("/* */", options()) -> unwind unreachable;
+    }
+}
diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
index 8d5991872e1..2a672e82970 100644
--- a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
+++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
@@ -55,16 +55,16 @@
       bb3: {
           StorageDead(_9);
 -         _0 = AllCopy { a: move _2, b: move _5, c: move _8 };
+-         StorageDead(_10);
 +         _0 = copy (*_1);
++         nop;
           StorageDead(_8);
-          StorageDead(_5);
-          StorageDead(_2);
--         StorageDead(_10);
 -         StorageDead(_7);
--         StorageDead(_4);
-+         nop;
 +         nop;
+          StorageDead(_5);
+-         StorageDead(_4);
 +         nop;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
index d0b50c597c4..5f9a8fe9547 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -53,12 +53,12 @@
       bb3: {
           StorageDead(_9);
           _0 = MyThing::<T> { v: move _2, i: move _5, a: move _8 };
-          StorageDead(_8);
-          StorageDead(_5);
-          StorageDead(_2);
           StorageDead(_10);
+          StorageDead(_8);
           StorageDead(_7);
+          StorageDead(_5);
           StorageDead(_4);
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
index b8f4f348530..0a02c2d4c0f 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -53,12 +53,12 @@
       bb3: {
           StorageDead(_9);
           _0 = MyThing::<T> { v: move _2, i: move _5, a: move _8 };
-          StorageDead(_8);
-          StorageDead(_5);
-          StorageDead(_2);
           StorageDead(_10);
+          StorageDead(_8);
           StorageDead(_7);
+          StorageDead(_5);
           StorageDead(_4);
+          StorageDead(_2);
           return;
       }
   
diff --git a/tests/run-make/core-no-fp-fmt-parse/rmake.rs b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
index 3586922f28e..a790ada40db 100644
--- a/tests/run-make/core-no-fp-fmt-parse/rmake.rs
+++ b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
@@ -5,7 +5,7 @@ use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
-        .edition("2021")
+        .edition("2024")
         .arg("-Dwarnings")
         .crate_type("rlib")
         .input(source_root().join("library/core/src/lib.rs"))
diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs
index 52252560e6f..06be95099b4 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]" \"\'a\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"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/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs
index f414c961627..ffc19b138a5 100644
--- a/tests/ui-fulldeps/run-compiler-twice.rs
+++ b/tests/ui-fulldeps/run-compiler-twice.rs
@@ -46,7 +46,7 @@ fn main() {
 fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
     let mut opts = Options::default();
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
-    opts.maybe_sysroot = Some(sysroot);
+    opts.sysroot = sysroot;
 
     if let Some(linker) = linker {
         opts.cg.linker = Some(linker.to_owned());
diff --git a/tests/ui/associated-type-bounds/hrtb.rs b/tests/ui/associated-type-bounds/hrtb.rs
index 1bf574f2e65..8ff7faec3a0 100644
--- a/tests/ui/associated-type-bounds/hrtb.rs
+++ b/tests/ui/associated-type-bounds/hrtb.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 
 trait A<'a> {}
 trait B<'b> {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
index 0a31cc67533..459f3ea1642 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
@@ -15,6 +15,10 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send(_: impl Send) {}
    |                    ^^^^ required by this bound in `is_send`
+help: consider further restricting the associated type
+   |
+LL | >() where <T as Foo>::method(..): Send {
+   |     ++++++++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/display.stderr b/tests/ui/associated-type-bounds/return-type-notation/display.stderr
index b895d796952..a614089ce40 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/display.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/display.stderr
@@ -11,6 +11,10 @@ note: required by a bound in `needs_trait`
    |
 LL | fn needs_trait(_: impl Trait) {}
    |                        ^^^^^ required by this bound in `needs_trait`
+help: consider further restricting the associated type
+   |
+LL | fn foo<T: Assoc>(t: T) where <T as Assoc>::method(..): Trait {
+   |                        +++++++++++++++++++++++++++++++++++++
 
 error[E0277]: the trait bound `impl Sized { <T as Assoc>::method_with_lt(..) }: Trait` is not satisfied
   --> $DIR/display.rs:16:17
@@ -25,6 +29,10 @@ note: required by a bound in `needs_trait`
    |
 LL | fn needs_trait(_: impl Trait) {}
    |                        ^^^^^ required by this bound in `needs_trait`
+help: consider further restricting the associated type
+   |
+LL | fn foo<T: Assoc>(t: T) where <T as Assoc>::method_with_lt(..): Trait {
+   |                        +++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0277]: the trait bound `impl Sized: Trait` is not satisfied
   --> $DIR/display.rs:18:17
diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed b/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed
new file mode 100644
index 00000000000..72c174a0ca0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed
@@ -0,0 +1,15 @@
+//@ run-rustfix
+
+#![allow(unused)]
+#![feature(return_type_notation)]
+
+trait Foo {
+    fn missing() -> impl Sized;
+}
+
+impl Foo for () {
+    //~^ ERROR not all trait items implemented, missing: `missing`
+fn missing() -> impl Sized { todo!() }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.rs b/tests/ui/associated-type-bounds/return-type-notation/rendering.rs
new file mode 100644
index 00000000000..4c9948d4c06
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.rs
@@ -0,0 +1,14 @@
+//@ run-rustfix
+
+#![allow(unused)]
+#![feature(return_type_notation)]
+
+trait Foo {
+    fn missing() -> impl Sized;
+}
+
+impl Foo for () {
+    //~^ ERROR not all trait items implemented, missing: `missing`
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr b/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr
new file mode 100644
index 00000000000..62fdeb059dd
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `missing`
+  --> $DIR/rendering.rs:10:1
+   |
+LL |     fn missing() -> impl Sized;
+   |     --------------------------- `missing` from trait
+...
+LL | impl Foo for () {
+   | ^^^^^^^^^^^^^^^ missing `missing` in implementation
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/associated-type-bounds/supertrait-defines-ty.rs b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
index ed1c1fa6f03..1c09ff3d3fb 100644
--- a/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
+++ b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 
 // Make sure that we don't look into associated type bounds when looking for
 // supertraits that define an associated type. Fixes #76593.
diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
index ee0e1326baa..3372ea5b853 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
+++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
@@ -9,11 +9,11 @@
 // We may want to lift this restriction in the future.
 
 pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
-//[min]~^^ ERROR `[u8; N]` is forbidden
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR `[u8; N]` is forbidden as the type of a const generic parameter
 
 pub struct SelfDependent<const N: [u8; N]>;
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
-//[min]~^^ ERROR `[u8; N]` is forbidden
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR `[u8; N]` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs b/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs
new file mode 100644
index 00000000000..83fe8c139f9
--- /dev/null
+++ b/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs
@@ -0,0 +1,8 @@
+#![feature(adt_const_params)]
+
+trait Trait<const N: usize> {
+    fn foo<const M: [u8; N]>() {}
+    //~^ ERROR the type of const parameters must not depend on other generic parameters
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr b/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr
new file mode 100644
index 00000000000..ed0a4b118d4
--- /dev/null
+++ b/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr
@@ -0,0 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-parent-param.rs:4:26
+   |
+LL |     fn foo<const M: [u8; N]>() {}
+   |                          ^ the type must not depend on the parameter `N`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
index 72d7001fdf1..c074e2e897e 100644
--- a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
+++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
@@ -2,19 +2,19 @@ error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:1:34
    |
 LL | struct Struct<const N: usize = { Self; 10 }>;
-   |                                  ^^^^ `Self` in generic parameter default
+   |                                  ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:4:30
    |
 LL | enum Enum<const N: usize = { Self; 10 }> { }
-   |                              ^^^^ `Self` in generic parameter default
+   |                              ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:7:32
    |
 LL | union Union<const N: usize = { Self; 10 }> { not_empty: () }
-   |                                ^^^^ `Self` in generic parameter default
+   |                                ^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/defaults/forward-declared.rs b/tests/ui/const-generics/defaults/forward-declared.rs
index ede3d873bdc..bd3abd4dcaa 100644
--- a/tests/ui/const-generics/defaults/forward-declared.rs
+++ b/tests/ui/const-generics/defaults/forward-declared.rs
@@ -1,13 +1,13 @@
 struct Foo<const N: usize = M, const M: usize = 10>;
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 enum Bar<const N: usize = M, const M: usize = 10> {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 struct Foo2<const N: usize = N>;
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 enum Bar2<const N: usize = N> {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/const-generics/defaults/forward-declared.stderr b/tests/ui/const-generics/defaults/forward-declared.stderr
index 4856c7a1fd2..4331996bffc 100644
--- a/tests/ui/const-generics/defaults/forward-declared.stderr
+++ b/tests/ui/const-generics/defaults/forward-declared.stderr
@@ -1,26 +1,26 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:1:29
    |
 LL | struct Foo<const N: usize = M, const M: usize = 10>;
-   |                             ^ defaulted generic parameters cannot be forward declared
+   |                             ^ cannot reference `M` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:4:27
    |
 LL | enum Bar<const N: usize = M, const M: usize = 10> {}
-   |                           ^ defaulted generic parameters cannot be forward declared
+   |                           ^ cannot reference `M` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:7:30
    |
 LL | struct Foo2<const N: usize = N>;
-   |                              ^ defaulted generic parameters cannot be forward declared
+   |                              ^ cannot reference `N` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:10:28
    |
 LL | enum Bar2<const N: usize = N> {}
-   |                            ^ defaulted generic parameters cannot be forward declared
+   |                            ^ cannot reference `N` before it is declared
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
index 91c1c80e07c..2abf7f44e20 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
@@ -4,8 +4,8 @@
 use std::marker::PhantomData;
 
 struct UsesConst<const N: [u8; M], const M: usize>;
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~^ ERROR: const parameter types cannot reference parameters before they are declared
 struct UsesType<const N: [T; 2], T>(PhantomData<T>);
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~^ ERROR: const parameter types cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
index b0dbdff8413..5526668b0be 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
@@ -1,15 +1,14 @@
-error[E0770]: the type of const parameters must not depend on other generic parameters
+error: const parameter types cannot reference parameters before they are declared
   --> $DIR/forward_declared_type.rs:6:32
    |
 LL | struct UsesConst<const N: [u8; M], const M: usize>;
-   |                                ^ the type must not depend on the parameter `M`
+   |                                ^ const parameter type cannot reference `M` before it is declared
 
-error[E0770]: the type of const parameters must not depend on other generic parameters
+error: const parameter types cannot reference parameters before they are declared
   --> $DIR/forward_declared_type.rs:8:27
    |
 LL | struct UsesType<const N: [T; 2], T>(PhantomData<T>);
-   |                           ^ the type must not depend on the parameter `T`
+   |                           ^ const parameter type cannot reference `T` before it is declared
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
index 29171c8006a..2d47797aef2 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
@@ -16,7 +16,7 @@ LL |     type Assoc<const N: Self>;
    = note: the only supported types are integers, `bool`, and `char`
 
 error: anonymous constants referencing generics are not yet supported
-  --> $DIR/references-parent-generics.rs:14:21
+  --> $DIR/references-parent-generics.rs:15:21
    |
 LL |     let x: T::Assoc<3>;
    |                     ^
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
index 64b41318814..68ce17317f6 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
@@ -1,16 +1,9 @@
-error: `Self` is forbidden as the type of a const generic parameter
+error[E0770]: the type of const parameters must not depend on other generic parameters
   --> $DIR/references-parent-generics.rs:7:25
    |
 LL |     type Assoc<const N: Self>;
-   |                         ^^^^
-   |
-   = note: the only supported types are integers, `bool`, and `char`
-
-error: anonymous constants referencing generics are not yet supported
-  --> $DIR/references-parent-generics.rs:14:21
-   |
-LL |     let x: T::Assoc<3>;
-   |                     ^
+   |                         ^^^^ the type must not depend on the parameter `Self`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
index 21994eb83b4..b91050d540c 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
@@ -5,14 +5,15 @@
 
 trait Foo {
     type Assoc<const N: Self>;
-    //~^ ERROR `Self` is forbidden as the type of a const generic parameter
+    //[nofeat]~^ ERROR the type of const parameters must not depend on other generic parameters
+    //[feat]~^^ ERROR `Self` is forbidden as the type of a const generic parameter
 }
 
 fn foo<T: Foo>() {
     // We used to end up feeding the type of this anon const to be `T`, but the anon const
     // doesn't inherit the generics of `foo`, which led to index oob errors.
     let x: T::Assoc<3>;
-    //~^ ERROR anonymous constants referencing generics are not yet supported
+    //[feat]~^ ERROR anonymous constants referencing generics are not yet supported
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
index 9f0b2efae96..dc28dea6851 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
@@ -4,11 +4,11 @@ error: generic parameters with a default must be trailing
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ defaulted generic parameters cannot be forward declared
+   |                     ^ cannot reference `N` before it is declared
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
index 320c9c1c84d..3f0e5e96fc8 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
@@ -13,11 +13,11 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    = note: type parameters may not be used in const expressions
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ defaulted generic parameters cannot be forward declared
+   |                     ^ cannot reference `N` before it is declared
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
index 2794ff3eaa9..d212cc425a0 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
@@ -6,7 +6,7 @@ struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
 //[min]~^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T = [u8; N], const N: usize>(T);
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 //~| ERROR generic parameters with a default
 
 fn main() {}
diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr
index 8328e19aac2..cee364b33f7 100644
--- a/tests/ui/consts/const-unsized.stderr
+++ b/tests/ui/consts/const-unsized.stderr
@@ -58,18 +58,18 @@ error[E0507]: cannot move out of a shared reference
 LL | static STATIC_BAR: str = *"bar";
    |                          ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
 
-error[E0161]: cannot move a value of type `str`
-  --> $DIR/const-unsized.rs:20:48
-   |
-LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-   |                                                ^^^^^^^^^ the size of `str` cannot be statically determined
-
 error[E0161]: cannot move a value of type `dyn Debug + Sync`
   --> $DIR/const-unsized.rs:20:38
    |
 LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
    |                                      ^^^^^^^ the size of `dyn Debug + Sync` cannot be statically determined
 
+error[E0161]: cannot move a value of type `str`
+  --> $DIR/const-unsized.rs:20:48
+   |
+LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
+   |                                                ^^^^^^^^^ the size of `str` cannot be statically determined
+
 error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0161, E0277, E0507.
diff --git a/tests/ui/delegation/fn-header-variadic.rs b/tests/ui/delegation/fn-header-variadic.rs
new file mode 100644
index 00000000000..2c83d64d0b3
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.rs
@@ -0,0 +1,25 @@
+//@ aux-crate:fn_header_aux=fn-header-aux.rs
+
+#![feature(c_variadic)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+}
+
+reuse to_reuse::variadic_fn;
+//~^ ERROR delegation to C-variadic functions is not allowed
+reuse fn_header_aux::variadic_fn_extern;
+//~^ ERROR delegation to C-variadic functions is not allowed
+
+fn main() {
+    unsafe {
+        variadic_fn(0);
+        variadic_fn(0, 1);
+        variadic_fn_extern(0);
+        variadic_fn_extern(0, 1);
+    }
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
+}
diff --git a/tests/ui/delegation/fn-header-variadic.stderr b/tests/ui/delegation/fn-header-variadic.stderr
new file mode 100644
index 00000000000..688a965fb4d
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.stderr
@@ -0,0 +1,22 @@
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:11:17
+   |
+LL |     pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+   |     ------------------------------------------------------------- callee defined here
+...
+LL | reuse to_reuse::variadic_fn;
+   |                 ^^^^^^^^^^^
+
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:13:22
+   |
+LL | reuse fn_header_aux::variadic_fn_extern;
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+  ::: $DIR/auxiliary/fn-header-aux.rs:7:1
+   |
+LL | pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
+   | -------------------------------------------------------------------- callee defined here
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs
index db20e1058e0..9de0d549f20 100644
--- a/tests/ui/delegation/fn-header.rs
+++ b/tests/ui/delegation/fn-header.rs
@@ -10,20 +10,17 @@
 mod to_reuse {
     pub unsafe fn unsafe_fn() {}
     pub extern "C" fn extern_fn() {}
-    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
     pub const fn const_fn() {}
     pub async fn async_fn() {}
 }
 
 reuse to_reuse::unsafe_fn;
 reuse to_reuse::extern_fn;
-reuse to_reuse::variadic_fn;
 reuse to_reuse::const_fn;
 reuse to_reuse::async_fn;
 
 reuse fn_header_aux::unsafe_fn_extern;
 reuse fn_header_aux::extern_fn_extern;
-reuse fn_header_aux::variadic_fn_extern;
 reuse fn_header_aux::const_fn_extern;
 reuse fn_header_aux::async_fn_extern;
 
@@ -46,12 +43,4 @@ fn main() {
     extern_fn_extern();
     let _: extern "C" fn() = extern_fn;
     let _: extern "C" fn() = extern_fn_extern;
-    unsafe {
-        variadic_fn(0);
-        variadic_fn(0, 1);
-        variadic_fn_extern(0);
-        variadic_fn_extern(0, 1);
-    }
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
 }
diff --git a/tests/ui/delegation/foreign-fn.rs b/tests/ui/delegation/foreign-fn.rs
new file mode 100644
index 00000000000..1d221da29ce
--- /dev/null
+++ b/tests/ui/delegation/foreign-fn.rs
@@ -0,0 +1,22 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![deny(unused_unsafe)]
+
+mod to_reuse {
+    unsafe extern "C" {
+        pub fn default_unsafe_foo();
+        pub unsafe fn unsafe_foo();
+        pub safe fn safe_foo();
+    }
+}
+
+reuse to_reuse::{default_unsafe_foo, unsafe_foo, safe_foo};
+
+fn main() {
+    let _: extern "C" fn() = default_unsafe_foo;
+    //~^ ERROR mismatched types
+    let _: extern "C" fn() = unsafe_foo;
+    //~^ ERROR mismatched types
+    let _: extern "C" fn() = safe_foo;
+}
diff --git a/tests/ui/delegation/foreign-fn.stderr b/tests/ui/delegation/foreign-fn.stderr
new file mode 100644
index 00000000000..f7d3dba4bb1
--- /dev/null
+++ b/tests/ui/delegation/foreign-fn.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/foreign-fn.rs:17:30
+   |
+LL |     let _: extern "C" fn() = default_unsafe_foo;
+   |            ---------------   ^^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `extern "C" fn()`
+                 found fn item `unsafe extern "C" fn() {default_unsafe_foo}`
+   = note: unsafe functions cannot be coerced into safe function pointers
+
+error[E0308]: mismatched types
+  --> $DIR/foreign-fn.rs:19:30
+   |
+LL |     let _: extern "C" fn() = unsafe_foo;
+   |            ---------------   ^^^^^^^^^^ expected safe fn, found unsafe fn
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `extern "C" fn()`
+                 found fn item `unsafe extern "C" fn() {unsafe_foo}`
+   = note: unsafe functions cannot be coerced into safe function pointers
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/delegation/ice-issue-138362.rs b/tests/ui/delegation/ice-issue-138362.rs
new file mode 100644
index 00000000000..c3066009855
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-138362.rs
@@ -0,0 +1,15 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait HasSelf {
+    fn method(self);
+}
+trait NoSelf {
+    fn method();
+}
+impl NoSelf for u8 {
+    reuse HasSelf::method;
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/ice-issue-138362.stderr b/tests/ui/delegation/ice-issue-138362.stderr
new file mode 100644
index 00000000000..9feddc9feae
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-138362.stderr
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/ice-issue-138362.rs:11:20
+   |
+LL |     reuse HasSelf::method;
+   |                    ^^^^^^ argument #1 is missing
+   |
+note: method defined here
+  --> $DIR/ice-issue-138362.rs:5:8
+   |
+LL |     fn method(self);
+   |        ^^^^^^ ----
+help: provide the argument
+   |
+LL |     reuse HasSelf::method(/* value */);
+   |                          +++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/error-codes/E0128.stderr b/tests/ui/error-codes/E0128.stderr
index c1ccb4c9e74..22f1e200e29 100644
--- a/tests/ui/error-codes/E0128.stderr
+++ b/tests/ui/error-codes/E0128.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/E0128.rs:1:14
    |
 LL | struct Foo<T=U, U=()> {
-   |              ^ defaulted generic parameters cannot be forward declared
+   |              ^ cannot reference `U` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generics/generic-non-trailing-defaults.rs b/tests/ui/generics/generic-non-trailing-defaults.rs
index 16ea71d48c8..ef500c42068 100644
--- a/tests/ui/generics/generic-non-trailing-defaults.rs
+++ b/tests/ui/generics/generic-non-trailing-defaults.rs
@@ -5,6 +5,6 @@ struct Vec<A = Heap, T>(A, T);
 
 struct Foo<A, B = Vec<C>, C>(A, B, C);
 //~^ ERROR generic parameters with a default must be trailing
-//~| ERROR generic parameters with a default cannot use
+//~| ERROR generic parameter defaults cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/generics/generic-non-trailing-defaults.stderr b/tests/ui/generics/generic-non-trailing-defaults.stderr
index 713ba091b86..d9057e932f5 100644
--- a/tests/ui/generics/generic-non-trailing-defaults.stderr
+++ b/tests/ui/generics/generic-non-trailing-defaults.stderr
@@ -10,11 +10,11 @@ error: generic parameters with a default must be trailing
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
    |               ^
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/generic-non-trailing-defaults.rs:6:23
    |
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
-   |                       ^ defaulted generic parameters cannot be forward declared
+   |                       ^ cannot reference `C` before it is declared
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generics/generic-type-params-forward-mention.rs b/tests/ui/generics/generic-type-params-forward-mention.rs
index 000c47095d2..4a8f76d34aa 100644
--- a/tests/ui/generics/generic-type-params-forward-mention.rs
+++ b/tests/ui/generics/generic-type-params-forward-mention.rs
@@ -1,6 +1,6 @@
 // Ensure that we get an error and not an ICE for this problematic case.
 struct Foo<T = Option<U>, U = bool>(T, U);
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 fn main() {
     let x: Foo;
 }
diff --git a/tests/ui/generics/generic-type-params-forward-mention.stderr b/tests/ui/generics/generic-type-params-forward-mention.stderr
index d7a6faa1941..ecc2387b48b 100644
--- a/tests/ui/generics/generic-type-params-forward-mention.stderr
+++ b/tests/ui/generics/generic-type-params-forward-mention.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/generic-type-params-forward-mention.rs:2:23
    |
 LL | struct Foo<T = Option<U>, U = bool>(T, U);
-   |                       ^ defaulted generic parameters cannot be forward declared
+   |                       ^ cannot reference `U` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
index f3a550801b9..f659a144def 100644
--- a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
+++ b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
@@ -2,37 +2,37 @@ error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25
    |
 LL | struct Snobound<'a, P = Self> { x: Option<&'a P> }
-   |                         ^^^^ `Self` in generic parameter default
+   |                         ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23
    |
 LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
-   |                       ^^^^ `Self` in generic parameter default
+   |                       ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24
    |
 LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
-   |                        ^^^^ `Self` in generic parameter default
+   |                        ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31
    |
 LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
-   |                               ^^^^ `Self` in generic parameter default
+   |                               ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29
    |
 LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
-   |                             ^^^^ `Self` in generic parameter default
+   |                             ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30
    |
 LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
-   |                              ^^^^ `Self` in generic parameter default
+   |                              ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/issues/issue-18183.stderr b/tests/ui/issues/issue-18183.stderr
index 11015d75d97..07fa4cdc753 100644
--- a/tests/ui/issues/issue-18183.stderr
+++ b/tests/ui/issues/issue-18183.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/issue-18183.rs:1:20
    |
 LL | pub struct Foo<Bar=Bar>(Bar);
-   |                    ^^^ defaulted generic parameters cannot be forward declared
+   |                    ^^^ cannot reference `Bar` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs
index e0723e016b3..8eb030a8ec9 100644
--- a/tests/ui/issues/issue-26812.rs
+++ b/tests/ui/issues/issue-26812.rs
@@ -1,5 +1,5 @@
 fn avg<T=T::Item>(_: T) {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 //~| ERROR defaults for type parameters
 //~| WARN previously accepted
 
diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr
index 4a18b23fd8b..bb60d67e287 100644
--- a/tests/ui/issues/issue-26812.stderr
+++ b/tests/ui/issues/issue-26812.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/issue-26812.rs:1:10
    |
 LL | fn avg<T=T::Item>(_: T) {}
-   |          ^^^^^^^ defaulted generic parameters cannot be forward declared
+   |          ^^^^^^^ cannot reference `T` before it is declared
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
   --> $DIR/issue-26812.rs:1:8
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
index 192b5eebdaa..4f1d339bc99 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
@@ -1,8 +1,8 @@
-error[E0275]: overflow evaluating the requirement `Loop == _`
+error[E0271]: type mismatch resolving `Loop normalizes-to _`
   --> $DIR/inherent-impls-overflow.rs:10:6
    |
 LL | impl Loop {}
-   |      ^^^^
+   |      ^^^^ types differ
 
 error: type parameter `T` is only used recursively
   --> $DIR/inherent-impls-overflow.rs:14:24
@@ -36,4 +36,5 @@ LL | impl Poly0<()> {}
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0275`.
+Some errors have detailed explanations: E0271, E0275.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
index 1397695a3fe..0d5ec7d1530 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
@@ -9,7 +9,7 @@ type Loop = Loop; //[current]~ ERROR overflow normalizing the type alias `Loop`
 
 impl Loop {}
 //[current]~^ ERROR overflow normalizing the type alias `Loop`
-//[next]~^^ ERROR overflow evaluating the requirement `Loop == _`
+//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _`
 
 type Poly0<T> = Poly1<(T,)>;
 //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
diff --git a/tests/ui/macros/macro-stmt-2.rs b/tests/ui/macros/macro-stmt-2.rs
new file mode 100644
index 00000000000..663d8ddc484
--- /dev/null
+++ b/tests/ui/macros/macro-stmt-2.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+//
+// This shows a tricky case for #124141, where `declare!(_x)` was incorrectly
+// being categorised as a `StmtKind::Expr` instead of a `StmtKind::MacCall` in
+// `parse_stmt_mac`.
+
+macro_rules! as_stmt { ($s:stmt) => { $s }; }
+
+macro_rules! declare { ($name:ident) => { let $name = 0u32; }; }
+
+fn main() { as_stmt!(declare!(_x)); }
diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs
index ca95e8fac05..b0a7f3e4650 100644
--- a/tests/ui/macros/nonterminal-matching.rs
+++ b/tests/ui/macros/nonterminal-matching.rs
@@ -16,7 +16,7 @@ macro complex_nonterminal($nt_item: item) {
         struct S;
     }
 
-    n!(a $nt_item b); //~ ERROR no rules expected item `enum E {}`
+    n!(a $nt_item b); //~ ERROR no rules expected `item` metavariable
 }
 
 simple_nonterminal!(a, 'a, (x, y, z)); // OK
@@ -32,7 +32,7 @@ macro_rules! foo {
     (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3`
     (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4`
     (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable
-    (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected statement `let abc = 0`
+    (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable
 }
 
 macro_rules! bar {
diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr
index ba2b3e213ad..2d9252fbfc1 100644
--- a/tests/ui/macros/nonterminal-matching.stderr
+++ b/tests/ui/macros/nonterminal-matching.stderr
@@ -1,4 +1,4 @@
-error: no rules expected item `enum E {}`
+error: no rules expected `item` metavariable
   --> $DIR/nonterminal-matching.rs:19:10
    |
 LL |     macro n(a $nt_item b) {
@@ -10,7 +10,7 @@ LL |     n!(a $nt_item b);
 LL | complex_nonterminal!(enum E {});
    | ------------------------------- in this macro invocation
    |
-note: while trying to match item `enum E {}`
+note: while trying to match `item` metavariable
   --> $DIR/nonterminal-matching.rs:15:15
    |
 LL |     macro n(a $nt_item b) {
@@ -89,7 +89,7 @@ LL |     (path a::b::c) => {};
    = 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 statement `let abc = 0`
+error: no rules expected `stmt` metavariable
   --> $DIR/nonterminal-matching.rs:35:35
    |
 LL |     (stmt $x:stmt) => { bar!(stmt $x); };
diff --git a/tests/ui/macros/std-2024-macros.rs b/tests/ui/macros/std-2024-macros.rs
new file mode 100644
index 00000000000..453c7ee16e5
--- /dev/null
+++ b/tests/ui/macros/std-2024-macros.rs
@@ -0,0 +1,13 @@
+// Tests a small handful of macros in the standard library how they handle the
+// new behavior introduced in 2024 that allows `const{}` expressions.
+
+//@ check-pass
+
+fn main() {
+    assert_eq!(0, const { 0 });
+    assert_eq!(const { 0 }, const { 0 });
+    assert_eq!(const { 0 }, 0);
+
+    let _: Vec<Vec<String>> = vec![const { vec![] }];
+    let _: Vec<Vec<String>> = vec![const { vec![] }; 10];
+}
diff --git a/tests/ui/proc-macro/expand-to-derive.stdout b/tests/ui/proc-macro/expand-to-derive.stdout
index 81fc52ea22d..3a16f23ecf2 100644
--- a/tests/ui/proc-macro/expand-to-derive.stdout
+++ b/tests/ui/proc-macro/expand-to-derive.stdout
@@ -44,52 +44,58 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                     Group {
                         delimiter: Brace,
                         stream: TokenStream [
-                            Punct {
-                                ch: '#',
-                                spacing: Alone,
-                                span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0),
-                            },
-                            Group {
-                                delimiter: Bracket,
-                                stream: TokenStream [
-                                    Ident {
-                                        ident: "rustc_dummy",
-                                        span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0),
-                                    },
-                                ],
-                                span: $DIR/expand-to-derive.rs:27:6: 27:41 (#0),
-                            },
-                            Ident {
-                                ident: "struct",
-                                span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0),
-                            },
-                            Ident {
-                                ident: "Inner",
-                                span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0),
-                            },
                             Group {
-                                delimiter: Brace,
+                                delimiter: None,
                                 stream: TokenStream [
-                                    Ident {
-                                        ident: "other_inner_field",
-                                        span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0),
-                                    },
                                     Punct {
-                                        ch: ':',
+                                        ch: '#',
                                         spacing: Alone,
-                                        span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0),
+                                        span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0),
+                                    },
+                                    Group {
+                                        delimiter: Bracket,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "rustc_dummy",
+                                                span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0),
+                                            },
+                                        ],
+                                        span: $DIR/expand-to-derive.rs:27:6: 27:41 (#0),
                                     },
                                     Ident {
-                                        ident: "u8",
-                                        span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0),
+                                        ident: "struct",
+                                        span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0),
                                     },
-                                    Punct {
-                                        ch: ',',
-                                        spacing: Alone,
-                                        span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0),
+                                    Ident {
+                                        ident: "Inner",
+                                        span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0),
+                                    },
+                                    Group {
+                                        delimiter: Brace,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "other_inner_field",
+                                                span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0),
+                                            },
+                                            Punct {
+                                                ch: ':',
+                                                spacing: Alone,
+                                                span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0),
+                                            },
+                                            Ident {
+                                                ident: "u8",
+                                                span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0),
+                                            },
+                                            Punct {
+                                                ch: ',',
+                                                spacing: Alone,
+                                                span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0),
+                                            },
+                                        ],
+                                        span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0),
                                     },
                                 ],
-                                span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0),
+                                span: $DIR/expand-to-derive.rs:19:17: 19:22 (#3),
                             },
                             Literal {
                                 kind: Integer,
diff --git a/tests/ui/proc-macro/nodelim-groups.rs b/tests/ui/proc-macro/nodelim-groups.rs
index 9acdc7023c0..8b0324214b9 100644
--- a/tests/ui/proc-macro/nodelim-groups.rs
+++ b/tests/ui/proc-macro/nodelim-groups.rs
@@ -19,4 +19,17 @@ macro_rules! expand_it {
 fn main() {
     expand_it!(1 + (25) + 1);
     expand_it!(("hello".len()) ("world".len()));
+    f();
+}
+
+// The key thing here is to produce a single `None`-delimited `Group`, even
+// though there is multiple levels of macros.
+macro_rules! m5 { ($e:expr) => { print_bang_consume!($e) }; }
+macro_rules! m4 { ($e:expr) => { m5!($e); } }
+macro_rules! m3 { ($e:expr) => { m4!($e); } }
+macro_rules! m2 { ($e:expr) => { m3!($e); } }
+macro_rules! m1 { ($e:expr) => { m2!($e); } }
+
+fn f() {
+    m1!(123);
 }
diff --git a/tests/ui/proc-macro/nodelim-groups.stdout b/tests/ui/proc-macro/nodelim-groups.stdout
index cdf851b535a..61001035c26 100644
--- a/tests/ui/proc-macro/nodelim-groups.stdout
+++ b/tests/ui/proc-macro/nodelim-groups.stdout
@@ -165,3 +165,18 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/nodelim-groups.rs:16:52: 16:59 (#8),
     },
 ]
+PRINT-BANG INPUT (DISPLAY): 123
+PRINT-BANG INPUT (DEBUG): TokenStream [
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Literal {
+                kind: Integer,
+                symbol: "123",
+                suffix: None,
+                span: $DIR/nodelim-groups.rs:34:9: 34:12 (#0),
+            },
+        ],
+        span: $DIR/nodelim-groups.rs:27:54: 27:56 (#16),
+    },
+]
diff --git a/tests/ui/rmeta/rmeta_bin-pass.rs b/tests/ui/rmeta/rmeta_bin-pass.rs
new file mode 100644
index 00000000000..7de4f3ba961
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin-pass.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: --emit=obj,metadata --crate-type=bin
+//@ aux-build:rmeta-meta.rs
+//@ no-prefer-dynamic
+//@ build-pass
+
+// Check that building a metadata bin crate works with a dependent, metadata
+// crate if linking is not requested.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+pub fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/tests/ui/rmeta/rmeta_bin.rs b/tests/ui/rmeta/rmeta_bin.rs
new file mode 100644
index 00000000000..c7d2050cd59
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin.rs
@@ -0,0 +1,14 @@
+//@ build-fail
+//@ compile-flags: --crate-type=bin
+//@ aux-build:rmeta-meta.rs
+//@ no-prefer-dynamic
+//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
+
+// Check that building a bin crate fails if a dependent crate is metadata-only.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/tests/ui/rmeta/rmeta_bin.stderr b/tests/ui/rmeta/rmeta_bin.stderr
new file mode 100644
index 00000000000..830169e032a
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin.stderr
@@ -0,0 +1,4 @@
+error: crate `rmeta_meta` required to be available in rlib format, but was not found in this form
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
index f3f9ce0bd87..3a574af9bba 100644
--- a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
+++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
@@ -26,14 +26,7 @@ extern "C" fn main(argc: core::ffi::c_int, argv: *const *const u8) -> core::ffi:
     let actual = unsafe {
         let mut actual: libc::sigaction = core::mem::zeroed();
         libc::sigaction(libc::SIGPIPE, core::ptr::null(), &mut actual);
-        #[cfg(not(target_os = "aix"))]
-        {
-            actual.sa_sigaction
-        }
-        #[cfg(target_os = "aix")]
-        {
-            actual.sa_union.__su_sigaction as libc::sighandler_t
-        }
+        actual.sa_sigaction
     };
 
     assert_eq!(actual, expected, "actual and expected SIGPIPE disposition in child differs");
diff --git a/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
index d16a2b4d8c8..3d93d50ca3f 100644
--- a/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
+++ b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
@@ -20,14 +20,7 @@ pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
         let actual = unsafe {
             let mut actual: libc::sigaction = std::mem::zeroed();
             libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual);
-            #[cfg(not(target_os = "aix"))]
-            {
-                actual.sa_sigaction
-            }
-            #[cfg(target_os = "aix")]
-            {
-                actual.sa_union.__su_sigaction as libc::sighandler_t
-            }
+            actual.sa_sigaction
         };
 
         let expected = match expected_handler {
diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
index 8fce0928273..f2af86be0a5 100644
--- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs
+++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
@@ -29,14 +29,7 @@ fn main() {
         // Install signal handler that runs on alternate signal stack.
         let mut action: sigaction = std::mem::zeroed();
         action.sa_flags = (SA_ONSTACK | SA_SIGINFO) as _;
-        #[cfg(not(target_os = "aix"))]
-        {
-            action.sa_sigaction = signal_handler as sighandler_t;
-        }
-        #[cfg(target_os = "aix")]
-        {
-            action.sa_union.__su_sigaction = signal_handler as sighandler_t;
-        }
+        action.sa_sigaction = signal_handler as sighandler_t;
         sigaction(SIGWINCH, &action, std::ptr::null_mut());
 
         // Send SIGWINCH on exit.
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs
index 5fea47a1be8..ca31d39de98 100644
--- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs
@@ -13,6 +13,6 @@ fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
 struct NoClone;
 
 fn main() {
-    let (a, b) = copy(NoClone); //~ ERROR
+    let (a, b) = copy(NoClone);
     println!("{:?} {:?}", a, b);
 }
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 07edc4ede76..3a3b99f6c5b 100644
--- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -6,31 +6,6 @@ LL | auto trait Magic: Copy {}
    |            |
    |            auto traits cannot have super traits or lifetime bounds
 
-error[E0277]: the trait bound `NoClone: Magic` is not satisfied
-  --> $DIR/supertrait-auto-trait.rs:16:23
-   |
-LL |     let (a, b) = copy(NoClone);
-   |                  ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
-   |                  |
-   |                  required by a bound introduced by this call
-   |
-note: required for `NoClone` to implement `Magic`
-  --> $DIR/supertrait-auto-trait.rs:8:12
-   |
-LL | auto trait Magic: Copy {}
-   |            ^^^^^
-note: required by a bound in `copy`
-  --> $DIR/supertrait-auto-trait.rs:10:12
-   |
-LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
-   |            ^^^^^ required by this bound in `copy`
-help: consider annotating `NoClone` with `#[derive(Copy)]`
-   |
-LL + #[derive(Copy)]
-LL | struct NoClone;
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0568.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0568`.
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
index 3238f028362..28fd66cd169 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
@@ -6,9 +6,11 @@
 trait Overflow {
     type Assoc;
 }
-impl<T> Overflow for T {
-    type Assoc = <T as Overflow>::Assoc;
-    //~^ ERROR: overflow
+impl<T> Overflow for T
+where
+    (T,): Overflow
+{
+    type Assoc = <(T,) as Overflow>::Assoc;
 }
 
 
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
index 294fa0d7613..34a45e93630 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -1,19 +1,15 @@
-error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc == _`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18
-   |
-LL |     type Assoc = <T as Overflow>::Assoc;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0119]: conflicting implementations of trait `Trait`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
+  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:20:1
    |
 LL | impl<T: Copy> Trait for T {}
    | ------------------------- first implementation here
 LL | struct LocalTy;
 LL | impl Trait for <LocalTy as Overflow>::Assoc {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+   |
+   = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc`
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`)
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0119, E0275.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs b/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs
new file mode 100644
index 00000000000..ec478aa02b7
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs
@@ -0,0 +1,21 @@
+// Regression test for trait-system-refactor-initiative#114.
+//
+// We previously treated the cycle when trying to use the
+// `<R as DimMin<C>>::Output: DimMin` where-bound when
+// normalizing `<R as DimMin<C>>::Output` as ambiguous, causing
+// this to error.
+
+//@ check-pass
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver
+
+pub trait DimMin<D> {
+    type Output;
+}
+pub fn repro<R: DimMin<C>, C>()
+where
+    <R as DimMin<C>>::Output: DimMin<C, Output = <R as DimMin<C>>::Output>,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs
new file mode 100644
index 00000000000..46dd6adf662
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs
@@ -0,0 +1,21 @@
+// If we treat known inductive cycles as errors, this test compiles
+// as normalizing `Overflow::Assoc<Overflow>` fails.
+//
+// As coherence already uses the new solver on stable, this change
+// would require an FCP.
+
+trait Trait {
+    type Assoc<T: Trait>;
+}
+
+struct Overflow;
+impl Trait for Overflow {
+    type Assoc<T: Trait> = <T as Trait>::Assoc<Overflow>;
+}
+
+trait Overlap<T, WfHack> {}
+impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
+impl<U> Overlap<u32, U> for Overflow {}
+//~^ ERROR conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr
new file mode 100644
index 00000000000..6605a28d547
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
+  --> $DIR/unproductive-in-coherence.rs:18:1
+   |
+LL | impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
+   | ----------------------------------------------------- first implementation here
+LL | impl<U> Overlap<u32, U> for Overflow {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Overflow`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
index 0f01a453b33..94a9484ecdc 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -13,12 +13,7 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
     needs_bar::<T::Assoc1>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
+    //~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
index 2b0e57966fe..6f5111a6193 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
@@ -1,59 +1,19 @@
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
   --> $DIR/recursive-self-normalization-2.rs:15:17
    |
 LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
+   |                 ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
    |
 note: required by a bound in `needs_bar`
   --> $DIR/recursive-self-normalization-2.rs:12:17
    |
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
-   |
-note: required by an implicit `Sized` bound in `needs_bar`
-  --> $DIR/recursive-self-normalization-2.rs:12:14
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |              ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn needs_bar<S: Bar + ?Sized>() {}
-   |                     ++++++++
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:5
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:5
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
+help: consider further restricting the associated type
    |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
+   |                                                                                       ++++++++++++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
index f435b48737e..f441ac499f9 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -9,12 +9,7 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
     needs_bar::<T::Assoc>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
+    //~^ ERROR the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
index af8504dcaee..c5518234687 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
@@ -1,59 +1,19 @@
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+error[E0277]: the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
   --> $DIR/recursive-self-normalization.rs:11:17
    |
 LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
+   |                 ^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo>::Assoc`
    |
 note: required by a bound in `needs_bar`
   --> $DIR/recursive-self-normalization.rs:8:17
    |
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
-   |
-note: required by an implicit `Sized` bound in `needs_bar`
-  --> $DIR/recursive-self-normalization.rs:8:14
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |              ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn needs_bar<S: Bar + ?Sized>() {}
-   |                     ++++++++
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:5
-   |
-LL |     needs_bar::<T::Assoc>();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:5
-   |
-LL |     needs_bar::<T::Assoc>();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
+help: consider further restricting the associated type
    |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() where <T as Foo>::Assoc: Bar {
+   |                                              ++++++++++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 55a5e4cd497..0fca91fd2f2 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -7,12 +7,12 @@ LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:22:18
+  --> $DIR/type-checking-test-4.rs:22:13
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
 LL |     let _ = x as &dyn Bar<'a, 'static>; // Error
-   |                  ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
   --> $DIR/type-checking-test-4.rs:28:5