about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-04-27 11:11:46 +0000
committerGitHub <noreply@github.com>2025-04-27 11:11:46 +0000
commit55872a19f9aa0cc9b6e8978c30758e8739ae5a17 (patch)
tree810a1c5fc6bda4807d26ad0d0059ebf71f1ccd37
parentea9037e1654d2fb7e29dca87679d3c18a713f82d (diff)
parent6c2fa0bce7c2673e6ef1a6776fcc279fa3342b72 (diff)
downloadrust-55872a19f9aa0cc9b6e8978c30758e8739ae5a17.tar.gz
rust-55872a19f9aa0cc9b6e8978c30758e8739ae5a17.zip
Merge pull request #4294 from rust-lang/rustup-2025-04-26
Automatic Rustup
-rw-r--r--.github/workflows/ci.yml13
-rw-r--r--Cargo.lock1
-rw-r--r--INSTALL.md25
-rw-r--r--compiler/rustc_ast/src/ast.rs14
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs2
-rw-r--r--compiler/rustc_attr_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs39
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs41
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs15
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs11
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs17
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs16
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs24
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs14
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_common.rs2
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs89
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs13
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/marker.rs22
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs20
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs25
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/lib.rs2
-rw-r--r--compiler/rustc_interface/src/lib.rs2
-rw-r--r--compiler/rustc_interface/src/util.rs21
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_macros/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs8
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs7
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/alias_relate.rs11
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs12
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs191
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs14
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs6
-rw-r--r--compiler/rustc_passes/src/errors.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs128
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_sanitizers/src/lib.rs2
-rw-r--r--compiler/rustc_serialize/src/opaque.rs2
-rw-r--r--compiler/rustc_serialize/src/opaque/mem_encoder.rs128
-rw-r--r--compiler/rustc_session/src/config/cfg.rs4
-rw-r--r--compiler/rustc_session/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs5
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_target/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs12
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs8
-rw-r--r--library/core/src/macros/mod.rs4
-rw-r--r--library/core/src/option.rs29
-rw-r--r--library/core/src/prelude/v1.rs1
-rw-r--r--library/core/src/result.rs32
-rw-r--r--library/std/Cargo.toml6
-rw-r--r--library/std/build.rs110
-rw-r--r--library/std/src/env.rs12
-rw-r--r--library/std/src/f128.rs270
-rw-r--r--library/std/src/f16.rs270
-rw-r--r--library/std/src/keyword_docs.rs9
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/prelude/v1.rs1
-rw-r--r--library/std/src/sys/args/mod.rs10
-rw-r--r--library/std/src/sys/args/uefi.rs5
-rw-r--r--library/std/src/sys/args/unix.rs5
-rw-r--r--library/std/src/sys/args/wasi.rs5
-rw-r--r--library/std/src/sys/args/windows.rs5
-rw-r--r--library/std/src/sys/args/xous.rs5
-rw-r--r--library/std/src/sys/env/common.rs48
-rw-r--r--library/std/src/sys/env/hermit.rs72
-rw-r--r--library/std/src/sys/env/mod.rs48
-rw-r--r--library/std/src/sys/env/sgx.rs55
-rw-r--r--library/std/src/sys/env/solid.rs96
-rw-r--r--library/std/src/sys/env/uefi.rs102
-rw-r--r--library/std/src/sys/env/unix.rs126
-rw-r--r--library/std/src/sys/env/unsupported.rs40
-rw-r--r--library/std/src/sys/env/wasi.rs102
-rw-r--r--library/std/src/sys/env/windows.rs133
-rw-r--r--library/std/src/sys/env/xous.rs54
-rw-r--r--library/std/src/sys/env/zkvm.rs32
-rw-r--r--library/std/src/sys/mod.rs1
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs8
-rw-r--r--library/std/src/sys/pal/hermit/os.rs118
-rw-r--r--library/std/src/sys/pal/sgx/os.rs100
-rw-r--r--library/std/src/sys/pal/solid/os.rs142
-rw-r--r--library/std/src/sys/pal/teeos/os.rs41
-rw-r--r--library/std/src/sys/pal/uefi/os.rs136
-rw-r--r--library/std/src/sys/pal/unix/os.rs173
-rw-r--r--library/std/src/sys/pal/unix/sync/condvar.rs5
-rw-r--r--library/std/src/sys/pal/unsupported/os.rs41
-rw-r--r--library/std/src/sys/pal/wasi/os.rs150
-rw-r--r--library/std/src/sys/pal/windows/os.rs135
-rw-r--r--library/std/src/sys/pal/xous/os.rs100
-rw-r--r--library/std/src/sys/pal/zkvm/os.rs62
-rw-r--r--library/std/src/sys/process/unix/unix.rs14
-rw-r--r--library/std/src/sys/process/unix/vxworks.rs4
-rw-r--r--library/std/tests/floats/f128.rs130
-rw-r--r--library/std/tests/floats/f16.rs122
-rw-r--r--library/std/tests/floats/lib.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs23
-rw-r--r--src/bootstrap/src/core/builder/tests.rs32
-rw-r--r--src/ci/citool/src/jobs.rs33
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile2
-rwxr-xr-xsrc/ci/docker/run.sh2
-rw-r--r--src/ci/github-actions/jobs.yml11
-rwxr-xr-xsrc/ci/scripts/free-disk-space.sh43
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md22
-rw-r--r--src/doc/rustdoc/src/read-documentation/search.md2
-rw-r--r--src/doc/rustdoc/src/unstable-features.md54
-rw-r--r--src/doc/rustdoc/src/write-documentation/documentation-tests.md37
-rw-r--r--src/doc/unstable-book/src/library-features/concat-idents.md3
m---------src/gcc0
-rw-r--r--src/librustdoc/config.rs23
-rw-r--r--src/librustdoc/doctest.rs6
-rw-r--r--src/librustdoc/doctest/markdown.rs8
-rw-r--r--src/librustdoc/doctest/rust.rs6
-rw-r--r--src/librustdoc/html/markdown.rs30
-rw-r--r--src/librustdoc/html/markdown/tests.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs26
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css5
-rw-r--r--src/librustdoc/lib.rs18
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs2
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs2
-rw-r--r--src/tools/compiletest/src/common.rs11
-rw-r--r--src/tools/compiletest/src/lib.rs7
-rw-r--r--src/tools/miri/cargo-miri/src/main.rs2
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs10
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/tidy/src/gcc_submodule.rs47
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--tests/run-make/doctests-runtool/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-default-output/output-default.stdout7
-rw-r--r--tests/rustdoc-gui/docblock-table-overflow.goml2
-rw-r--r--tests/rustdoc-gui/impl-doc-indent.goml16
-rw-r--r--tests/rustdoc-gui/item-info-overflow.goml2
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs26
-rw-r--r--tests/rustdoc/doctest/auxiliary/doctest-runtool.rs21
-rw-r--r--tests/rustdoc/doctest/doctest-runtool.rs13
-rw-r--r--tests/ui/asm/naked-invalid-attr.rs9
-rw-r--r--tests/ui/asm/naked-invalid-attr.stderr19
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_.stderr8
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_math_.stderr8
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_.stderr8
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_math_.stderr8
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.rs5
-rw-r--r--tests/ui/coercion/issue-73886.stderr7
-rw-r--r--tests/ui/coercion/non-primitive-cast-135412.fixed10
-rw-r--r--tests/ui/coercion/non-primitive-cast-135412.rs10
-rw-r--r--tests/ui/coercion/non-primitive-cast-135412.stderr29
-rw-r--r--tests/ui/copy-a-resource.rs21
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr11
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.rs12
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.stderr39
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents2.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents2.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents3.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents3.stderr4
-rw-r--r--tests/ui/float/target-has-reliable-nightly-float.rs31
-rw-r--r--tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.rs23
-rw-r--r--tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr26
-rw-r--r--tests/ui/issues/issue-32950.rs1
-rw-r--r--tests/ui/issues/issue-32950.stderr4
-rw-r--r--tests/ui/issues/issue-50403.rs1
-rw-r--r--tests/ui/issues/issue-50403.stderr2
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.rs1
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr62
-rw-r--r--tests/ui/macros/no-matching-rule.rs (renamed from tests/ui/fail-simple.rs)0
-rw-r--r--tests/ui/macros/no-matching-rule.stderr (renamed from tests/ui/fail-simple.stderr)2
-rw-r--r--tests/ui/methods/clone-missing.rs19
-rw-r--r--tests/ui/methods/clone-missing.stderr (renamed from tests/ui/copy-a-resource.stderr)2
-rw-r--r--tests/ui/modules/mod-pub-access.rs11
-rw-r--r--tests/ui/path.rs7
-rw-r--r--tests/ui/resolve/fn-item-cant-capture-dynamic-env.rs (renamed from tests/ui/capture1.rs)0
-rw-r--r--tests/ui/resolve/fn-item-cant-capture-dynamic-env.stderr (renamed from tests/ui/capture1.stderr)2
-rw-r--r--tests/ui/simd/intrinsic/generic-comparison-pass.rs4
-rw-r--r--tests/ui/syntax-extension-minor.rs1
-rw-r--r--tests/ui/traits/next-solver/normalize/eager-norm-pre-normalizes-to.rs44
-rw-r--r--tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs1
-rw-r--r--tests/ui/transmute/auxiliary/unnecessary-transmute-path-remap-ice-140277-trans.rs10
-rw-r--r--tests/ui/transmute/unnecessary-transmute-path-remap-ice-140277.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs2
-rw-r--r--tests/ui/type-alias/type-param.rs11
-rw-r--r--tests/ui/type-param.rs10
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.rs1
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout2
222 files changed, 3219 insertions, 2144 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index efe4157aae2..93316b9cff7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -91,6 +91,17 @@ jobs:
         # Check the `calculate_matrix` job to see how is the matrix defined.
         include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}
     steps:
+      - name: Install cargo in AWS CodeBuild
+        if: matrix.codebuild
+        run: |
+          # Check if cargo is installed
+          if ! command -v cargo &> /dev/null; then
+            echo "Cargo not found, installing Rust..."
+            curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal
+            # Make cargo available in PATH
+            echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+          fi
+
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
 
@@ -165,6 +176,8 @@ jobs:
         run: src/ci/scripts/install-ninja.sh
 
       - name: enable ipv6 on Docker
+        # Don't run on codebuild because systemctl is not available
+        if: ${{ !matrix.codebuild }}
         run: src/ci/scripts/enable-docker-ipv6.sh
 
       # Disable automatic line ending conversion (again). On Windows, when we're
diff --git a/Cargo.lock b/Cargo.lock
index cfdd873e80f..ee6726eae51 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4158,7 +4158,6 @@ dependencies = [
  "rustc_data_structures",
  "rustc_index",
  "rustc_macros",
- "rustc_serialize",
  "rustc_type_ir",
  "rustc_type_ir_macros",
  "tracing",
diff --git a/INSTALL.md b/INSTALL.md
index 30e08201d6d..98eb825cd10 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -75,8 +75,31 @@ See [the rustc-dev-guide for more info][sysllvm].
 
 2. Configure the build settings:
 
+   If you're unsure which build configurations to use and need a good default, you
+   can run the interactive `x.py setup` command. This will guide you through selecting
+   a config profile, setting up the LSP, configuring a Git hook, etc.
+
+   With `configure` script, you can handle multiple configurations in a single
+   command which is useful to create complex/advanced config files. For example:
+
    ```sh
-   ./configure
+   ./configure --build=aarch64-unknown-linux-gnu \
+      --enable-full-tools \
+      --enable-profiler \
+      --enable-sanitizers \
+      --enable-compiler-docs \
+      --set target.aarch64-unknown-linux-gnu.linker=clang \
+      --set target.aarch64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \
+      --set target.aarch64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
+      --set llvm.link-shared=true \
+      --set llvm.thin-lto=true \
+      --set llvm.libzstd=true \
+      --set llvm.ninja=false \
+      --set rust.debug-assertions=false \
+      --set rust.jemalloc \
+      --set rust.use-lld=true \
+      --set rust.lto=thin \
+      --set rust.codegen-units=1
    ```
 
    If you plan to use `x.py install` to create an installation, you can either
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 1532ca77f71..8986430141b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1927,7 +1927,7 @@ impl AttrArgs {
 }
 
 /// Delimited arguments, as used in `#[attr()/[]/{}]` or `mac!()/[]/{}`.
-#[derive(Clone, Encodable, Decodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct DelimArgs {
     pub dspan: DelimSpan,
     pub delim: Delimiter, // Note: `Delimiter::Invisible` never occurs
@@ -1942,18 +1942,6 @@ impl DelimArgs {
     }
 }
 
-impl<CTX> HashStable<CTX> for DelimArgs
-where
-    CTX: crate::HashStableContext,
-{
-    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
-        let DelimArgs { dspan, delim, tokens } = self;
-        dspan.hash_stable(ctx, hasher);
-        delim.hash_stable(ctx, hasher);
-        tokens.hash_stable(ctx, hasher);
-    }
-}
-
 /// Represents a macro definition.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MacroDef {
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 294c6c9ba7a..1471262d2d6 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(bootstrap, feature(let_chains))]
 #![doc(
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(deny(warnings)))
@@ -14,7 +15,6 @@
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 534e85e8bcb..1e14b4d6723 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,12 +32,12 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(exact_size_is_empty)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
@@ -916,7 +916,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs {
-        DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() }
+        args.clone()
     }
 
     /// Lower an associated item constraint.
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 093199cf342..7956057f88e 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -4,11 +4,11 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iter_is_partitioned)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index c61b44b273d..679fe935484 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -1,7 +1,7 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 63597b37cb5..55c3df003fe 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
 use std::ops::Deref;
 use std::sync::LazyLock;
 
-use rustc_ast::{self as ast, DelimArgs};
+use rustc_ast as ast;
 use rustc_attr_data_structures::AttributeKind;
 use rustc_errors::{DiagCtxtHandle, Diagnostic};
 use rustc_feature::Features;
@@ -315,11 +315,7 @@ impl<'sess> AttributeParser<'sess> {
     fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
         match args {
             ast::AttrArgs::Empty => AttrArgs::Empty,
-            ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(DelimArgs {
-                dspan: args.dspan,
-                delim: args.delim,
-                tokens: args.tokens.clone(),
-            }),
+            ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can extract literals to handle
             // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index 249e71ef70d..b9692c01e2c 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -77,8 +77,8 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 134f30ed6f5..0de4bd67f0c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -49,7 +49,7 @@ impl<'tcx> UniverseInfo<'tcx> {
         UniverseInfo::RelateTys { expected, found }
     }
 
-    pub(crate) fn report_error(
+    pub(crate) fn report_erroneous_element(
         &self,
         mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
         placeholder: ty::PlaceholderRegion,
@@ -68,7 +68,7 @@ impl<'tcx> UniverseInfo<'tcx> {
                 mbcx.buffer_error(err);
             }
             UniverseInfo::TypeOp(ref type_op_info) => {
-                type_op_info.report_error(mbcx, placeholder, error_element, cause);
+                type_op_info.report_erroneous_element(mbcx, placeholder, error_element, cause);
             }
             UniverseInfo::Other => {
                 // FIXME: This error message isn't great, but it doesn't show
@@ -145,8 +145,11 @@ pub(crate) trait TypeOpInfo<'tcx> {
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<Diag<'infcx>>;
 
+    /// Constraints require that `error_element` appear in the
+    ///  values of `placeholder`, but this cannot be proven to
+    /// hold. Report an error.
     #[instrument(level = "debug", skip(self, mbcx))]
-    fn report_error(
+    fn report_erroneous_element(
         &self,
         mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
         placeholder: ty::PlaceholderRegion,
@@ -190,12 +193,7 @@ pub(crate) trait TypeOpInfo<'tcx> {
         let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
 
         debug!(?nice_error);
-
-        if let Some(nice_error) = nice_error {
-            mbcx.buffer_error(nice_error);
-        } else {
-            mbcx.buffer_error(self.fallback_error(tcx, span));
-        }
+        mbcx.buffer_error(nice_error.unwrap_or_else(|| self.fallback_error(tcx, span)));
     }
 }
 
@@ -450,7 +448,8 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
         ty::ReVar(vid) => universe_of_region(vid),
         _ => ty::UniverseIndex::ROOT,
     };
-    let matches =
+    // Are the two regions the same?
+    let regions_the_same =
         |a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
             (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
             _ => a_region == b_region,
@@ -459,7 +458,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
         |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint {
             Constraint::RegSubReg(sub, sup)
                 if ((exact && sup == placeholder_region)
-                    || (!exact && matches(sup, placeholder_region)))
+                    || (!exact && regions_the_same(sup, placeholder_region)))
                     && sup != sub =>
             {
                 Some((sub, cause.clone()))
@@ -468,23 +467,21 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
                 if (exact
                     && sup == placeholder_region
                     && !universe_of_region(vid).can_name(placeholder_universe))
-                    || (!exact && matches(sup, placeholder_region)) =>
+                    || (!exact && regions_the_same(sup, placeholder_region)) =>
             {
                 Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
             }
             _ => None,
         };
-    let mut info = region_constraints
-        .constraints
-        .iter()
-        .find_map(|(constraint, cause)| check(constraint, cause, true));
-    if info.is_none() {
-        info = region_constraints
+
+    let mut find_culprit = |exact_match: bool| {
+        region_constraints
             .constraints
             .iter()
-            .find_map(|(constraint, cause)| check(constraint, cause, false));
-    }
-    let (sub_region, cause) = info?;
+            .find_map(|(constraint, cause)| check(constraint, cause, exact_match))
+    };
+
+    let (sub_region, cause) = find_culprit(true).or_else(|| find_culprit(false))?;
 
     debug!(?sub_region, "cause = {:#?}", cause);
     let error = match (error_region, sub_region.kind()) {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 4423edb0605..3bec07afa0f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -405,7 +405,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     let universe = placeholder.universe;
                     let universe_info = self.regioncx.universe_info(universe);
 
-                    universe_info.report_error(self, placeholder, error_element, cause);
+                    universe_info.report_erroneous_element(self, placeholder, error_element, cause);
                 }
 
                 RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 83a9827e8f8..51d37353520 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2,12 +2,12 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f8af9e59f63..c256051c122 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1628,30 +1628,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
         debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
 
-        for error_element in self.scc_values.elements_contained_in(longer_fr_scc) {
-            match error_element {
-                RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {}
-                // If we have some bound universal region `'a`, then the only
-                // elements it can contain is itself -- we don't know anything
-                // else about it!
-                RegionElement::PlaceholderRegion(placeholder1) => {
-                    if placeholder == placeholder1 {
-                        continue;
-                    }
-                }
-            }
-
+        // If we have some bound universal region `'a`, then the only
+        // elements it can contain is itself -- we don't know anything
+        // else about it!
+        if let Some(error_element) = self
+            .scc_values
+            .elements_contained_in(longer_fr_scc)
+            .find(|e| *e != RegionElement::PlaceholderRegion(placeholder))
+        {
+            // Stop after the first error, it gets too noisy otherwise, and does not provide more information.
             errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
                 longer_fr,
                 error_element,
                 placeholder,
             });
-
-            // Stop after the first error, it gets too noisy otherwise, and does not provide more
-            // information.
-            break;
+        } else {
+            debug!("check_bound_universal_region: all bounds satisfied");
         }
-        debug!("check_bound_universal_region: all bounds satisfied");
     }
 
     #[instrument(level = "debug", skip(self, infcx, errors_buffer))]
@@ -2071,7 +2064,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 constraint.category
             };
 
-            match category {
+            let interest = match category {
                 // Returns usually provide a type to blame and have specially written diagnostics,
                 // so prioritize them.
                 ConstraintCategory::Return(_) => 0,
@@ -2123,9 +2116,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // specific, and are not used for relations that would make sense to blame.
                 ConstraintCategory::BoringNoLocation => 6,
                 // Do not blame internal constraints.
-                ConstraintCategory::Internal => 7,
-                ConstraintCategory::IllegalUniverse => 8,
-            }
+                ConstraintCategory::IllegalUniverse => 7,
+                ConstraintCategory::Internal => 8,
+            };
+
+            debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}");
+
+            interest
         };
 
         let best_choice = if blame_source {
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index d9ac5b5cb13..f1427218cdb 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -21,7 +21,7 @@ rustc_index::newtype_index! {
 
 /// An individual element in a region value -- the value of a
 /// particular region variable consists of a set of these elements.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
 pub(crate) enum RegionElement {
     /// A point in the control-flow graph.
     Location(Location),
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index bcd40f980e6..70e817db2a6 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -12,7 +13,6 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(rustdoc_internals)]
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 9d9e790289c..ab09a6f8b38 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -41,8 +41,8 @@ use std::sync::Arc;
 
 use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings::{self, Configurable};
-use rustc_codegen_ssa::CodegenResults;
 use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_codegen_ssa::{CodegenResults, TargetConfig};
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_session::Session;
@@ -178,7 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
         }
     }
 
-    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
+    fn target_config(&self, sess: &Session) -> TargetConfig {
         // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
         let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
             // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
@@ -197,7 +197,16 @@ impl CodegenBackend for CraneliftCodegenBackend {
         };
         // FIXME do `unstable_target_features` properly
         let unstable_target_features = target_features.clone();
-        (target_features, unstable_target_features)
+
+        TargetConfig {
+            target_features,
+            unstable_target_features,
+            // Cranelift does not yet support f16 or f128
+            has_reliable_f16: false,
+            has_reliable_f16_math: false,
+            has_reliable_f128: false,
+            has_reliable_f128_math: false,
+        }
     }
 
     fn print_version(&self) {
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index fd898c59707..452d3f22dc5 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2025-04-17"
+channel = "nightly-2025-04-25"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index dbdf37ee6c9..396c6d57950 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -165,10 +165,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         let mut input_registers = vec![];
 
         for op in rust_operands {
-            if let InlineAsmOperandRef::In { reg, .. } = *op {
-                if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
-                    input_registers.push(reg_name);
-                }
+            if let InlineAsmOperandRef::In { reg, .. } = *op
+                && let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg)
+            {
+                input_registers.push(reg_name);
             }
         }
 
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index a63da6b6e27..918195364ff 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -33,12 +33,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
-        if value.get_type() == self.bool_type.make_pointer() {
-            if let Some(pointee) = typ.get_pointee() {
-                if pointee.dyncast_vector().is_some() {
-                    panic!()
-                }
-            }
+        if value.get_type() == self.bool_type.make_pointer()
+            && let Some(pointee) = typ.get_pointee()
+            && pointee.dyncast_vector().is_some()
+        {
+            panic!()
         }
         // NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
         // SIMD builtins require a constant value.
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index acb39374628..0a67bd7bc71 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -242,10 +242,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
 
         let global = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
-            if let Some(global) = self.get_declared_value(sym) {
-                if self.val_ty(global) != self.type_ptr_to(gcc_type) {
-                    span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
-                }
+            if let Some(global) = self.get_declared_value(sym)
+                && self.val_ty(global) != self.type_ptr_to(gcc_type)
+            {
+                span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
             }
 
             let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 55e01687400..f3ced864395 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -126,14 +126,15 @@ fn make_mir_scope<'gcc, 'tcx>(
         return;
     };
 
-    if let Some(ref vars) = *variables {
-        if !vars.contains(scope) && scope_data.inlined.is_none() {
-            // Do not create a DIScope if there are no variables defined in this
-            // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
-            debug_context.scopes[scope] = parent_scope;
-            instantiated.insert(scope);
-            return;
-        }
+    if let Some(ref vars) = *variables
+        && !vars.contains(scope)
+        && scope_data.inlined.is_none()
+    {
+        // Do not create a DIScope if there are no variables defined in this
+        // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
+        debug_context.scopes[scope] = parent_scope;
+        instantiated.insert(scope);
+        return;
     }
 
     let loc = cx.lookup_debug_loc(scope_data.span.lo());
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 202764d5649..2b053abdd19 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -55,7 +55,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
             )
         } else if let Some(feature) = feature.strip_prefix('-') {
             // FIXME: Why do we not remove implied features on "-" here?
-            // We do the equivalent above in `target_features_cfg`.
+            // We do the equivalent above in `target_config`.
             // See <https://github.com/rust-lang/rust/issues/134792>.
             all_rust_features.push((false, feature));
         } else if !feature.is_empty() && diagnostics {
@@ -136,14 +136,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
         });
     features.extend(feats);
 
-    if diagnostics {
-        if let Some(f) = check_tied_features(sess, &featsmap) {
-            sess.dcx().emit_err(TargetFeatureDisableOrEnable {
-                features: f,
-                span: None,
-                missing_features: None,
-            });
-        }
+    if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
+        sess.dcx().emit_err(TargetFeatureDisableOrEnable {
+            features: f,
+            span: None,
+            missing_features: None,
+        });
     }
 
     features
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 624fdb4043c..2c5a7871683 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -22,7 +22,7 @@
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
 #![deny(clippy::pattern_type_mismatch)]
-#![allow(clippy::needless_lifetimes)]
+#![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]
 
 // Some "regular" crates we want to share with rustc
 extern crate object;
@@ -102,7 +102,7 @@ use rustc_codegen_ssa::back::write::{
 };
 use rustc_codegen_ssa::base::codegen_crate;
 use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
-use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
+use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::IntoDynSyncSend;
 use rustc_errors::DiagCtxtHandle;
@@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
             .join(sess)
     }
 
-    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
-        target_features_cfg(sess, &self.target_info)
+    fn target_config(&self, sess: &Session) -> TargetConfig {
+        target_config(sess, &self.target_info)
     }
 }
 
@@ -485,10 +485,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
 }
 
 /// Returns the features that should be set in `cfg(target_feature)`.
-fn target_features_cfg(
-    sess: &Session,
-    target_info: &LockedTargetInfo,
-) -> (Vec<Symbol>, Vec<Symbol>) {
+fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
     // TODO(antoyo): use global_gcc_features.
     let f = |allow_unstable| {
         sess.target
@@ -523,5 +520,14 @@ fn target_features_cfg(
 
     let target_features = f(false);
     let unstable_target_features = f(true);
-    (target_features, unstable_target_features)
+
+    TargetConfig {
+        target_features,
+        unstable_target_features,
+        // There are no known bugs with GCC support for f16 or f128
+        has_reliable_f16: true,
+        has_reliable_f16_math: true,
+        has_reliable_f128: true,
+        has_reliable_f128_math: true,
+    }
 }
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index ae98b3d0b56..5745acce6fe 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -102,10 +102,10 @@ fn uncached_gcc_type<'gcc, 'tcx>(
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
             if let (&ty::Adt(def, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
+                && def.is_enum()
+                && !def.variants().is_empty()
             {
-                if def.is_enum() && !def.variants().is_empty() {
-                    write!(&mut name, "::{}", def.variant(index).name).unwrap();
-                }
+                write!(&mut name, "::{}", def.variant(index).name).unwrap();
             }
             if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
@@ -264,10 +264,10 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     }
 
     fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        if let BackendRepr::Scalar(ref scalar) = self.backend_repr {
-            if scalar.is_bool() {
-                return cx.type_i1();
-            }
+        if let BackendRepr::Scalar(ref scalar) = self.backend_repr
+            && scalar.is_bool()
+        {
+            return cx.type_i1();
         }
         self.gcc_type(cx)
     }
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
index 64c932a2658..d5a0d71c4b2 100644
--- a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
@@ -1,5 +1,7 @@
 //! The common code for `tests/lang_tests_*.rs`
 
+#![allow(clippy::uninlined_format_args)]
+
 use std::env::{self, current_dir};
 use std::path::{Path, PathBuf};
 use std::process::Command;
diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
index c1254c51ce9..e627886a9d5 100644
--- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
@@ -5,6 +5,7 @@
 //   stdout: 10
 //     10
 //     42
+//     1
 
 #![feature(no_core)]
 #![no_std]
@@ -21,6 +22,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3
     )
 }
 
+static mut ONE: usize = 1;
+
 #[no_mangle]
 extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
     let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
@@ -28,6 +31,10 @@ extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
         libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
         libc::printf(b"%ld\n\0" as *const u8 as *const i8, d);
         libc::printf(b"%ld\n\0" as *const u8 as *const i8, j);
+
+        let ptr = ONE as *mut usize;
+        let value = ptr as usize;
+        libc::printf(b"%ld\n\0" as *const u8 as *const i8, value);
     }
     0
 }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 425381b0ffa..e8010ec9fc4 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -6,6 +6,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -15,7 +16,6 @@
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![feature(slice_as_array)]
 #![feature(try_blocks)]
@@ -29,7 +29,7 @@ use back::owned_target_machine::OwnedTargetMachine;
 use back::write::{create_informational_target_machine, create_target_machine};
 use context::SimpleCx;
 use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
-use llvm_util::target_features_cfg;
+use llvm_util::target_config;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@@ -37,7 +37,7 @@ use rustc_codegen_ssa::back::write::{
     CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
 };
 use rustc_codegen_ssa::traits::*;
-use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
+use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::{DiagCtxtHandle, FatalError};
 use rustc_metadata::EncodedMetadata;
@@ -338,8 +338,8 @@ impl CodegenBackend for LlvmCodegenBackend {
         llvm_util::print_version();
     }
 
-    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
-        target_features_cfg(sess)
+    fn target_config(&self, sess: &Session) -> TargetConfig {
+        target_config(sess)
     }
 
     fn codegen_crate<'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 36e35f81392..ae1bdac1655 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -6,6 +6,7 @@ use std::sync::Once;
 use std::{ptr, slice, str};
 
 use libc::c_int;
+use rustc_codegen_ssa::TargetConfig;
 use rustc_codegen_ssa::base::wants_wasm_eh;
 use rustc_codegen_ssa::codegen_attrs::check_tied_features;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -302,7 +303,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
 /// Must express features in the way Rust understands them.
 ///
 /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
-pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
+pub(crate) fn target_config(sess: &Session) -> TargetConfig {
     // Add base features for the target.
     // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
     // The reason is that if LLVM considers a feature implied but we do not, we don't want that to
@@ -402,7 +403,89 @@ pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>)
 
     let target_features = f(false);
     let unstable_target_features = f(true);
-    (target_features, unstable_target_features)
+    let mut cfg = TargetConfig {
+        target_features,
+        unstable_target_features,
+        has_reliable_f16: true,
+        has_reliable_f16_math: true,
+        has_reliable_f128: true,
+        has_reliable_f128_math: true,
+    };
+
+    update_target_reliable_float_cfg(sess, &mut cfg);
+    cfg
+}
+
+/// Determine whether or not experimental float types are reliable based on known bugs.
+fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
+    let target_arch = sess.target.arch.as_ref();
+    let target_os = sess.target.options.os.as_ref();
+    let target_env = sess.target.options.env.as_ref();
+    let target_abi = sess.target.options.abi.as_ref();
+    let target_pointer_width = sess.target.pointer_width;
+
+    cfg.has_reliable_f16 = match (target_arch, target_os) {
+        // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
+        ("s390x", _) => false,
+        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
+        ("arm64ec", _) => false,
+        // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
+        ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
+        // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
+        ("csky", _) => false,
+        ("hexagon", _) => false,
+        ("powerpc" | "powerpc64", _) => false,
+        ("sparc" | "sparc64", _) => false,
+        ("wasm32" | "wasm64", _) => false,
+        // `f16` support only requires that symbols converting to and from `f32` are available. We
+        // provide these in `compiler-builtins`, so `f16` should be available on all platforms that
+        // do not have other ABI issues or LLVM crashes.
+        _ => true,
+    };
+
+    cfg.has_reliable_f128 = match (target_arch, target_os) {
+        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
+        ("arm64ec", _) => false,
+        // Selection bug <https://github.com/llvm/llvm-project/issues/96432>
+        ("mips64" | "mips64r6", _) => false,
+        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
+        ("nvptx64", _) => false,
+        // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
+        // list at <https://github.com/rust-lang/rust/issues/116909>)
+        ("powerpc" | "powerpc64", _) => false,
+        // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838>
+        ("sparc", _) => false,
+        // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
+        // not fail if our compiler-builtins is linked.
+        ("x86", _) => false,
+        // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
+        ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
+        // There are no known problems on other platforms, so the only requirement is that symbols
+        // are available. `compiler-builtins` provides all symbols required for core `f128`
+        // support, so this should work for everything else.
+        _ => true,
+    };
+
+    cfg.has_reliable_f16_math = match (target_arch, target_os) {
+        // x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
+        ("x86" | "x86_64", _) => false,
+        // Assume that working `f16` means working `f16` math for most platforms, since
+        // operations just go through `f32`.
+        _ => true,
+    } && cfg.has_reliable_f16;
+
+    cfg.has_reliable_f128_math = match (target_arch, target_os) {
+        // LLVM lowers `fp128` math to `long double` symbols even on platforms where
+        // `long double` is not IEEE binary128. See
+        // <https://github.com/llvm/llvm-project/issues/44744>.
+        //
+        // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
+        // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
+        // (ld is 80-bit extended precision).
+        ("x86_64", _) => false,
+        (_, "linux") if target_pointer_width == 64 => true,
+        _ => false,
+    } && cfg.has_reliable_f128;
 }
 
 pub(crate) fn print_version() {
@@ -686,7 +769,7 @@ pub(crate) fn global_llvm_features(
                 )
             } else if let Some(feature) = feature.strip_prefix('-') {
                 // FIXME: Why do we not remove implied features on "-" here?
-                // We do the equivalent above in `target_features_cfg`.
+                // We do the equivalent above in `target_config`.
                 // See <https://github.com/rust-lang/rust/issues/134792>.
                 all_rust_features.push((false, feature));
             } else if !feature.is_empty() {
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 5b2ed69535b..b67c871cac9 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -2,13 +2,13 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(rustdoc_internals)]
 #![feature(string_from_utf8_lossy_owned)]
@@ -235,6 +235,24 @@ pub struct CrateInfo {
     pub lint_levels: CodegenLintLevels,
 }
 
+/// Target-specific options that get set in `cfg(...)`.
+///
+/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
+pub struct TargetConfig {
+    /// Options to be set in `cfg(target_features)`.
+    pub target_features: Vec<Symbol>,
+    /// Options to be set in `cfg(target_features)`, but including unstable features.
+    pub unstable_target_features: Vec<Symbol>,
+    /// Option for `cfg(target_has_reliable_f16)`, true if `f16` basic arithmetic works.
+    pub has_reliable_f16: bool,
+    /// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work.
+    pub has_reliable_f16_math: bool,
+    /// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works.
+    pub has_reliable_f128: bool,
+    /// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work.
+    pub has_reliable_f128_math: bool,
+}
+
 #[derive(Encodable, Decodable)]
 pub struct CodegenResults {
     pub modules: Vec<CompiledModule>,
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 65fd843e7a5..e6b50cc7c0c 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -18,7 +18,7 @@ use super::write::WriteBackendMethods;
 use crate::back::archive::ArArchiveBuilderBuilder;
 use crate::back::link::link_binary;
 use crate::back::write::TargetMachineFactoryFn;
-use crate::{CodegenResults, ModuleCodegen};
+use crate::{CodegenResults, ModuleCodegen, TargetConfig};
 
 pub trait BackendTypes {
     type Value: CodegenObject;
@@ -50,8 +50,15 @@ pub trait CodegenBackend {
     /// - The second is like the first, but also includes unstable features.
     ///
     /// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
-    fn target_features_cfg(&self, _sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
-        (vec![], vec![])
+    fn target_config(&self, _sess: &Session) -> TargetConfig {
+        TargetConfig {
+            target_features: vec![],
+            unstable_target_features: vec![],
+            has_reliable_f16: true,
+            has_reliable_f16_math: true,
+            has_reliable_f128: true,
+            has_reliable_f128_math: true,
+        }
     }
 
     fn print_passes(&self) {}
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index da52d60ae59..7a0c2543c30 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -1,12 +1,12 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 #![feature(slice_ptr_get)]
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 5f07cfef133..dfd9bd32076 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -39,8 +39,15 @@ impls_dyn_send_neg!(
     [std::io::StderrLock<'_>]
 );
 
-#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
-// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
+#[cfg(any(
+    unix,
+    target_os = "hermit",
+    all(target_vendor = "fortanix", target_env = "sgx"),
+    target_os = "solid_asp3",
+    target_os = "wasi",
+    target_os = "xous"
+))]
+// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
 impl !DynSend for std::env::VarsOs {}
 
 macro_rules! already_send {
@@ -106,8 +113,15 @@ impls_dyn_sync_neg!(
     [std::sync::mpsc::Sender<T> where T]
 );
 
-#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
-// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
+#[cfg(any(
+    unix,
+    target_os = "hermit",
+    all(target_vendor = "fortanix", target_env = "sgx"),
+    target_os = "solid_asp3",
+    target_os = "wasi",
+    target_os = "xous"
+))]
+// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
 impl !DynSync for std::env::VarsOs {}
 
 macro_rules! already_sync {
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 40cc82727a5..d18fa892814 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -7,10 +7,10 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(decl_macro)]
-#![feature(let_chains)]
 #![feature(panic_backtrace_config)]
 #![feature(panic_update_hook)]
 #![feature(result_flattening)]
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index c0c5dba4677..6f37bad9bb4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -7,6 +7,7 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
@@ -17,7 +18,6 @@
 #![feature(default_field_values)]
 #![feature(error_reporter)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 4222c9fe906..79f838e2e33 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,11 +1,11 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(rust_logo)]
 #![feature(array_windows)]
 #![feature(associated_type_defaults)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(macro_metavar_expr)]
 #![feature(map_try_insert)]
 #![feature(proc_macro_diagnostic)]
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 43ba67e7dc6..a5e6b1c00d6 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -40,6 +40,26 @@ const GATED_CFGS: &[GatedCfg] = &[
     // this is consistent with naming of the compiler flag it's for
     (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
     (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
+    (
+        sym::target_has_reliable_f16,
+        sym::cfg_target_has_reliable_f16_f128,
+        Features::cfg_target_has_reliable_f16_f128,
+    ),
+    (
+        sym::target_has_reliable_f16_math,
+        sym::cfg_target_has_reliable_f16_f128,
+        Features::cfg_target_has_reliable_f16_f128,
+    ),
+    (
+        sym::target_has_reliable_f128,
+        sym::cfg_target_has_reliable_f16_f128,
+        Features::cfg_target_has_reliable_f16_f128,
+    ),
+    (
+        sym::target_has_reliable_f128_math,
+        sym::cfg_target_has_reliable_f16_f128,
+        Features::cfg_target_has_reliable_f16_f128,
+    ),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index cbc121e3632..12e254ab549 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -205,6 +205,8 @@ declare_features! (
     (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
     /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
     (internal, cfg_emscripten_wasm_eh, "1.86.0", None),
+    /// Allows checking whether or not the backend correctly supports unstable float types.
+    (internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
     /// Allows identifying the `compiler_builtins` crate.
     (internal, compiler_builtins, "1.13.0", None),
     /// Allows writing custom MIR
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index a84857e3597..32064f96dd6 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,12 +4,12 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(closure_track_caller)]
 #![feature(debug_closure_helpers)]
 #![feature(exhaustive_patterns)]
-#![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index e1ad8124aea..309b8f2c761 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -67,7 +68,6 @@ This API is completely unstable and subject to change.
 #![feature(if_let_guard)]
 #![feature(iter_from_coroutine)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 #![feature(slice_partition_dedup)]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index ff4385c3bcc..779fae80f19 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2,7 +2,7 @@
 //! the definitions in this file have equivalents in `rustc_ast_pretty`.
 
 // tidy-alphabetical-start
-#![feature(let_chains)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index b19d9efe2c6..caf36ba47bd 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -501,12 +501,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             .must_apply_modulo_regions()
                         {
                             label = false;
-                            err.span_suggestion(
-                                self.span,
-                                "consider using the `From` trait instead",
-                                format!("{}::from({})", self.cast_ty, snippet),
-                                Applicability::MaybeIncorrect,
-                            );
+                            if let ty::Adt(def, args) = self.cast_ty.kind() {
+                                err.span_suggestion_verbose(
+                                    self.span,
+                                    "consider using the `From` trait instead",
+                                    format!(
+                                        "{}::from({})",
+                                        fcx.tcx.value_path_str_with_args(def.did(), args),
+                                        snippet
+                                    ),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            } else {
+                                err.span_suggestion(
+                                    self.span,
+                                    "consider using the `From` trait instead",
+                                    format!("{}::from({})", self.cast_ty, snippet),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            };
                         }
                     }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index af8ec373934..c3717b4efa4 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -1,11 +1,11 @@
 // tidy-alphabetical-start
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(array_windows)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index ece18f4ea64..8b2aab42042 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -16,12 +16,12 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(extend_one)]
 #![feature(iterator_try_collect)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![recursion_limit = "512"] // For rustdoc
 // tidy-alphabetical-end
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 67e0be93523..41280707183 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,8 +1,8 @@
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(decl_macro)]
 #![feature(file_buffered)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index c3a939f1ab0..4d346b50c80 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -38,14 +38,25 @@ pub(crate) fn add_configuration(
     codegen_backend: &dyn CodegenBackend,
 ) {
     let tf = sym::target_feature;
+    let tf_cfg = codegen_backend.target_config(sess);
 
-    let (target_features, unstable_target_features) = codegen_backend.target_features_cfg(sess);
+    sess.unstable_target_features.extend(tf_cfg.unstable_target_features.iter().copied());
+    sess.target_features.extend(tf_cfg.target_features.iter().copied());
 
-    sess.unstable_target_features.extend(unstable_target_features.iter().copied());
+    cfg.extend(tf_cfg.target_features.into_iter().map(|feat| (tf, Some(feat))));
 
-    sess.target_features.extend(target_features.iter().copied());
-
-    cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
+    if tf_cfg.has_reliable_f16 {
+        cfg.insert((sym::target_has_reliable_f16, None));
+    }
+    if tf_cfg.has_reliable_f16_math {
+        cfg.insert((sym::target_has_reliable_f16_math, None));
+    }
+    if tf_cfg.has_reliable_f128 {
+        cfg.insert((sym::target_has_reliable_f128, None));
+    }
+    if tf_cfg.has_reliable_f128_math {
+        cfg.insert((sym::target_has_reliable_f128_math, None));
+    }
 
     if sess.crt_static(None) {
         cfg.insert((tf, Some(sym::crt_dash_static)));
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c8c556fc2ac..b910d6a138e 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
@@ -28,7 +29,6 @@
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iter_order_by)]
-#![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index edb25e79904..62ca7ce3ca9 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,7 +1,7 @@
 // tidy-alphabetical-start
 #![allow(rustc::default_hash_types)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 3b44c44fcb9..3931be1654a 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(coroutines)]
@@ -8,7 +9,6 @@
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(iter_from_coroutine)]
-#![feature(let_chains)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
 #![feature(never_type)]
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 8fe2cc7101b..df025aeebf0 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(allocator_api)]
@@ -48,7 +49,6 @@
 #![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
 #![feature(iter_from_coroutine)]
-#![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 02e316dfc3d..551d816941b 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -121,11 +121,10 @@ impl<'tcx> Predicate<'tcx> {
     /// unsoundly accept some programs. See #91068.
     #[inline]
     pub fn allow_normalization(self) -> bool {
-        // Keep this in sync with the one in `rustc_type_ir::inherent`!
         match self.kind().skip_binder() {
-            PredicateKind::Clause(ClauseKind::WellFormed(_))
-            | PredicateKind::AliasRelate(..)
-            | PredicateKind::NormalizesTo(..) => false,
+            PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => {
+                false
+            }
             PredicateKind::Clause(ClauseKind::Trait(_))
             | PredicateKind::Clause(ClauseKind::HostEffect(..))
             | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
@@ -137,6 +136,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::Coerce(_)
             | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
             | PredicateKind::ConstEquate(_, _)
+            | PredicateKind::NormalizesTo(..)
             | PredicateKind::Ambiguous => true,
         }
     }
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 8e96d46dac2..a051cf570b7 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -3,10 +3,10 @@
 // tidy-alphabetical-start
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index a0efc623b8e..38f82b12746 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,10 +1,10 @@
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(assert_matches)]
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(exact_size_is_empty)]
 #![feature(file_buffered)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
index 8be782dcbf0..4aff127908e 100644
--- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
+++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
@@ -87,11 +87,8 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
             && let Some((func_def_id, _)) = func.const_fn_def()
             && self.tcx.is_intrinsic(func_def_id, sym::transmute)
             && let span = self.body.source_info(location).span
-            && let Some(lint) = self.is_unnecessary_transmute(
-                func,
-                self.tcx.sess.source_map().span_to_snippet(arg).expect("ok"),
-                span,
-            )
+            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(arg)
+            && let Some(lint) = self.is_unnecessary_transmute(func, snippet, span)
             && let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes)
         {
             self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint);
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 6977d23bd0e..5db62b7e902 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(bootstrap, feature(let_chains))]
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
@@ -7,7 +8,6 @@
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(never_type)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 8f6914f3d72..8469e0f17a6 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,9 +1,9 @@
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(array_windows)]
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(let_chains)]
 // tidy-alphabetical-end
 
 use rustc_hir::lang_items::LangItem;
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 63aa60f2f26..36d53901d9e 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -9,7 +9,6 @@ derive-where = "1.2.7"
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
-rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
 rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
 tracing = "0.1"
@@ -20,7 +19,6 @@ default = ["nightly"]
 nightly = [
     "dep:rustc_data_structures",
     "dep:rustc_macros",
-    "dep:rustc_serialize",
     "rustc_index/nightly",
     "rustc_type_ir/nightly",
 ]
diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
index 0fc313e33b3..f7bd4600943 100644
--- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
@@ -16,6 +16,7 @@
 //! relate them structurally.
 
 use rustc_type_ir::inherent::*;
+use rustc_type_ir::solve::GoalSource;
 use rustc_type_ir::{self as ty, Interner};
 use tracing::{instrument, trace};
 
@@ -49,7 +50,10 @@ where
         // Structurally normalize the lhs.
         let lhs = if let Some(alias) = lhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(lhs);
-            self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
+            self.add_goal(
+                GoalSource::TypeRelating,
+                goal.with(cx, ty::NormalizesTo { alias, term }),
+            );
             term
         } else {
             lhs
@@ -58,7 +62,10 @@ where
         // Structurally normalize the rhs.
         let rhs = if let Some(alias) = rhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(rhs);
-            self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
+            self.add_goal(
+                GoalSource::TypeRelating,
+                goal.with(cx, ty::NormalizesTo { alias, term }),
+            );
             term
         } else {
             rhs
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index d56b0e5847e..04f80a056f9 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -22,7 +22,7 @@ use tracing::{debug, instrument, trace};
 use crate::canonicalizer::Canonicalizer;
 use crate::delegate::SolverDelegate;
 use crate::resolve::EagerResolver;
-use crate::solve::eval_ctxt::{CurrentGoalKind, NestedGoals};
+use crate::solve::eval_ctxt::CurrentGoalKind;
 use crate::solve::{
     CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal,
     MaybeCause, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput,
@@ -112,13 +112,9 @@ where
         // by `try_evaluate_added_goals()`.
         let (certainty, normalization_nested_goals) = match self.current_goal_kind {
             CurrentGoalKind::NormalizesTo => {
-                let NestedGoals { normalizes_to_goals, goals } =
-                    std::mem::take(&mut self.nested_goals);
-                if cfg!(debug_assertions) {
-                    assert!(normalizes_to_goals.is_empty());
-                    if goals.is_empty() {
-                        assert!(matches!(goals_certainty, Certainty::Yes));
-                    }
+                let goals = std::mem::take(&mut self.nested_goals);
+                if goals.is_empty() {
+                    assert!(matches!(goals_certainty, Certainty::Yes));
                 }
                 (certainty, NestedNormalizationGoals(goals))
             }
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 9994c85d0d0..27ca8787db5 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
@@ -1,8 +1,8 @@
+use std::mem;
 use std::ops::ControlFlow;
 
-use derive_where::derive_where;
 #[cfg(feature = "nightly")]
-use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
+use rustc_macros::HashStable_NoContext;
 use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
@@ -14,7 +14,6 @@ use rustc_type_ir::{
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
     TypingMode,
 };
-use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use tracing::{instrument, trace};
 
 use crate::coherence;
@@ -114,7 +113,7 @@ where
 
     pub(super) search_graph: &'a mut SearchGraph<D>,
 
-    nested_goals: NestedGoals<I>,
+    nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
 
     pub(super) origin_span: I::Span,
 
@@ -129,38 +128,6 @@ where
     pub(super) inspect: ProofTreeBuilder<D>,
 }
 
-#[derive_where(Clone, Debug, Default; I: Interner)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
-#[cfg_attr(
-    feature = "nightly",
-    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
-)]
-struct NestedGoals<I: Interner> {
-    /// These normalizes-to goals are treated specially during the evaluation
-    /// loop. In each iteration we take the RHS of the projection, replace it with
-    /// a fresh inference variable, and only after evaluating that goal do we
-    /// equate the fresh inference variable with the actual RHS of the predicate.
-    ///
-    /// This is both to improve caching, and to avoid using the RHS of the
-    /// projection predicate to influence the normalizes-to candidate we select.
-    ///
-    /// Forgetting to replace the RHS with a fresh inference variable when we evaluate
-    /// this goal results in an ICE..
-    pub normalizes_to_goals: Vec<Goal<I, ty::NormalizesTo<I>>>,
-    /// The rest of the goals which have not yet processed or remain ambiguous.
-    pub goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
-}
-
-impl<I: Interner> NestedGoals<I> {
-    fn new() -> Self {
-        Self { normalizes_to_goals: Vec::new(), goals: Vec::new() }
-    }
-
-    fn is_empty(&self) -> bool {
-        self.normalizes_to_goals.is_empty() && self.goals.is_empty()
-    }
-}
-
 #[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum GenerateProofTree {
@@ -332,7 +299,7 @@ where
         let mut ecx = EvalCtxt {
             delegate,
             search_graph: &mut search_graph,
-            nested_goals: NestedGoals::new(),
+            nested_goals: Default::default(),
             inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree),
 
             // Only relevant when canonicalizing the response,
@@ -385,7 +352,7 @@ where
             predefined_opaques_in_body: input.predefined_opaques_in_body,
             max_input_universe: canonical_input.canonical.max_universe,
             search_graph,
-            nested_goals: NestedGoals::new(),
+            nested_goals: Default::default(),
             origin_span: I::Span::dummy(),
             tainted: Ok(()),
             inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
@@ -629,78 +596,83 @@ where
     /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
     fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
         let cx = self.cx();
-        let mut goals = core::mem::take(&mut self.nested_goals);
-
         // If this loop did not result in any progress, what's our final certainty.
         let mut unchanged_certainty = Some(Certainty::Yes);
-        for goal in goals.normalizes_to_goals {
-            // Replace the goal with an unconstrained infer var, so the
-            // RHS does not affect projection candidate assembly.
-            let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
-            let unconstrained_goal = goal.with(
-                cx,
-                ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
-            );
-
-            let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
-                GoalEvaluationKind::Nested,
-                GoalSource::TypeRelating,
-                unconstrained_goal,
-            )?;
-            // Add the nested goals from normalization to our own nested goals.
-            trace!(?nested_goals);
-            goals.goals.extend(nested_goals);
-
-            // Finally, equate the goal's RHS with the unconstrained var.
+        for (source, goal) in mem::take(&mut self.nested_goals) {
+            // We treat normalizes-to goals specially here. In each iteration we take the
+            // RHS of the projection, replace it with a fresh inference variable, and only
+            // after evaluating that goal do we equate the fresh inference variable with the
+            // actual RHS of the predicate.
             //
-            // SUBTLE:
-            // We structurally relate aliases here. This is necessary
-            // as we otherwise emit a nested `AliasRelate` goal in case the
-            // returned term is a rigid alias, resulting in overflow.
+            // This is both to improve caching, and to avoid using the RHS of the
+            // projection predicate to influence the normalizes-to candidate we select.
             //
-            // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
-            // start out as an unconstrained inference variable so any aliases get
-            // fully normalized when instantiating it.
-            //
-            // FIXME: Strictly speaking this may be incomplete if the normalized-to
-            // type contains an ambiguous alias referencing bound regions. We should
-            // consider changing this to only use "shallow structural equality".
-            self.eq_structurally_relating_aliases(
-                goal.param_env,
-                goal.predicate.term,
-                unconstrained_rhs,
-            )?;
-
-            // We only look at the `projection_ty` part here rather than
-            // looking at the "has changed" return from evaluate_goal,
-            // because we expect the `unconstrained_rhs` part of the predicate
-            // to have changed -- that means we actually normalized successfully!
-            let with_resolved_vars = self.resolve_vars_if_possible(goal);
-            if goal.predicate.alias != with_resolved_vars.predicate.alias {
-                unchanged_certainty = None;
-            }
-
-            match certainty {
-                Certainty::Yes => {}
-                Certainty::Maybe(_) => {
-                    self.nested_goals.normalizes_to_goals.push(with_resolved_vars);
-                    unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
+            // Forgetting to replace the RHS with a fresh inference variable when we evaluate
+            // this goal results in an ICE.
+            if let Some(pred) = goal.predicate.as_normalizes_to() {
+                // We should never encounter higher-ranked normalizes-to goals.
+                let pred = pred.no_bound_vars().unwrap();
+                // Replace the goal with an unconstrained infer var, so the
+                // RHS does not affect projection candidate assembly.
+                let unconstrained_rhs = self.next_term_infer_of_kind(pred.term);
+                let unconstrained_goal =
+                    goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
+
+                let (NestedNormalizationGoals(nested_goals), _, certainty) =
+                    self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?;
+                // Add the nested goals from normalization to our own nested goals.
+                trace!(?nested_goals);
+                self.nested_goals.extend(nested_goals);
+
+                // Finally, equate the goal's RHS with the unconstrained var.
+                //
+                // SUBTLE:
+                // We structurally relate aliases here. This is necessary
+                // as we otherwise emit a nested `AliasRelate` goal in case the
+                // returned term is a rigid alias, resulting in overflow.
+                //
+                // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
+                // start out as an unconstrained inference variable so any aliases get
+                // fully normalized when instantiating it.
+                //
+                // FIXME: Strictly speaking this may be incomplete if the normalized-to
+                // type contains an ambiguous alias referencing bound regions. We should
+                // consider changing this to only use "shallow structural equality".
+                self.eq_structurally_relating_aliases(
+                    goal.param_env,
+                    pred.term,
+                    unconstrained_rhs,
+                )?;
+
+                // We only look at the `projection_ty` part here rather than
+                // looking at the "has changed" return from evaluate_goal,
+                // because we expect the `unconstrained_rhs` part of the predicate
+                // to have changed -- that means we actually normalized successfully!
+                let with_resolved_vars = self.resolve_vars_if_possible(goal);
+                if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias {
+                    unchanged_certainty = None;
                 }
-            }
-        }
 
-        for (source, goal) in goals.goals {
-            let (has_changed, certainty) =
-                self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
-            if has_changed == HasChanged::Yes {
-                unchanged_certainty = None;
-            }
+                match certainty {
+                    Certainty::Yes => {}
+                    Certainty::Maybe(_) => {
+                        self.nested_goals.push((source, with_resolved_vars));
+                        unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
+                    }
+                }
+            } else {
+                let (has_changed, certainty) =
+                    self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
+                if has_changed == HasChanged::Yes {
+                    unchanged_certainty = None;
+                }
 
-            match certainty {
-                Certainty::Yes => {}
-                Certainty::Maybe(_) => {
-                    self.nested_goals.goals.push((source, goal));
-                    unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
+                match certainty {
+                    Certainty::Yes => {}
+                    Certainty::Maybe(_) => {
+                        self.nested_goals.push((source, goal));
+                        unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
+                    }
                 }
             }
         }
@@ -717,23 +689,12 @@ where
         self.delegate.cx()
     }
 
-    #[instrument(level = "trace", skip(self))]
-    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::TypeRelating,
-            goal.param_env,
-        ));
-        self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
-        self.nested_goals.normalizes_to_goals.push(goal);
-    }
-
     #[instrument(level = "debug", skip(self))]
     pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
         goal.predicate =
             goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
         self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
-        self.nested_goals.goals.push((source, goal));
+        self.nested_goals.push((source, goal));
     }
 
     #[instrument(level = "trace", skip(self, goals))]
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 6a8e0790f7c..f22b275bc44 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -412,20 +412,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub(crate) fn add_normalizes_to_goal(
-        &mut self,
-        delegate: &D,
-        max_input_universe: ty::UniverseIndex,
-        goal: Goal<I, ty::NormalizesTo<I>>,
-    ) {
-        self.add_goal(
-            delegate,
-            max_input_universe,
-            GoalSource::TypeRelating,
-            goal.with(delegate.cx(), goal.predicate),
-        );
-    }
-
     pub(crate) fn add_goal(
         &mut self,
         delegate: &D,
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 896e348a12d..e73d68e2037 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -4,13 +4,13 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(debug_closure_helpers)]
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(string_from_utf8_lossy_owned)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 3b1b0300e62..a61d446a3a9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -683,10 +683,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     }
 
                     if !other_attr.has_any_name(ALLOW_LIST) {
+                        let path = other_attr.path();
+                        let path: Vec<_> = path.iter().map(|s| s.as_str()).collect();
+                        let other_attr_name = path.join("::");
+
                         self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
                             span: other_attr.span(),
                             naked_span: attr.span(),
-                            attr: other_attr.name().unwrap(),
+                            attr: other_attr_name,
                         });
 
                         return;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 4052264b051..b1b4b9ee927 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1249,7 +1249,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
     pub span: Span,
     #[label(passes_naked_attribute)]
     pub naked_span: Span,
-    pub attr: Symbol,
+    pub attr: String,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 93ff0f66d69..c7bb00df796 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -6,9 +6,9 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![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)]
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 176dcbf6da4..f63d8b2d79f 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,7 +6,7 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 #![allow(unused_crate_dependencies)]
-#![cfg_attr(feature = "rustc", feature(let_chains))]
+#![cfg_attr(all(feature = "rustc", bootstrap), feature(let_chains))]
 // tidy-alphabetical-end
 
 pub mod constructor;
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 48e29c823a2..e57d12dce51 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,9 +1,9 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![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)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index ac24628447d..d2bcde14383 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -46,6 +46,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::{Idx, IndexVec};
+use rustc_serialize::opaque::mem_encoder::MemEncoder;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use tracing::{debug, instrument};
@@ -105,22 +106,12 @@ impl SerializedDepGraph {
     ) -> impl Iterator<Item = SerializedDepNodeIndex> + Clone {
         let header = self.edge_list_indices[source];
         let mut raw = &self.edge_list_data[header.start()..];
-        // Figure out where the edge list for `source` ends by getting the start index of the next
-        // edge list, or the end of the array if this is the last edge.
-        let end = self
-            .edge_list_indices
-            .get(source + 1)
-            .map(|h| h.start())
-            .unwrap_or_else(|| self.edge_list_data.len() - DEP_NODE_PAD);
-
-        // The number of edges for this node is implicitly stored in the combination of the byte
-        // width and the length.
+
         let bytes_per_index = header.bytes_per_index();
-        let len = (end - header.start()) / bytes_per_index;
 
         // LLVM doesn't hoist EdgeHeader::mask so we do it ourselves.
         let mask = header.mask();
-        (0..len).map(move |_| {
+        (0..header.num_edges).map(move |_| {
             // Doing this slicing in this order ensures that the first bounds check suffices for
             // all the others.
             let index = &raw[..DEP_NODE_SIZE];
@@ -163,6 +154,7 @@ impl SerializedDepGraph {
 #[derive(Debug, Clone, Copy)]
 struct EdgeHeader {
     repr: usize,
+    num_edges: u32,
 }
 
 impl EdgeHeader {
@@ -205,9 +197,14 @@ impl SerializedDepGraph {
 
         let graph_bytes = d.len() - (2 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position();
 
-        let mut nodes = IndexVec::with_capacity(node_count);
-        let mut fingerprints = IndexVec::with_capacity(node_count);
-        let mut edge_list_indices = IndexVec::with_capacity(node_count);
+        let mut nodes = IndexVec::from_elem_n(
+            DepNode { kind: D::DEP_KIND_NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) },
+            node_count,
+        );
+        let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_count);
+        let mut edge_list_indices =
+            IndexVec::from_elem_n(EdgeHeader { repr: 0, num_edges: 0 }, node_count);
+
         // This estimation assumes that all of the encoded bytes are for the edge lists or for the
         // fixed-size node headers. But that's not necessarily true; if any edge list has a length
         // that spills out of the size we can bit-pack into SerializedNodeHeader then some of the
@@ -226,11 +223,14 @@ impl SerializedDepGraph {
             let node_header =
                 SerializedNodeHeader::<D> { bytes: d.read_array(), _marker: PhantomData };
 
-            let _i: SerializedDepNodeIndex = nodes.push(node_header.node());
-            debug_assert_eq!(_i.index(), _index);
+            let index = node_header.index();
+
+            let node = &mut nodes[index];
+            // Make sure there's no duplicate indices in the dep graph.
+            assert!(node_header.node().kind != D::DEP_KIND_NULL && node.kind == D::DEP_KIND_NULL);
+            *node = node_header.node();
 
-            let _i: SerializedDepNodeIndex = fingerprints.push(node_header.fingerprint());
-            debug_assert_eq!(_i.index(), _index);
+            fingerprints[index] = node_header.fingerprint();
 
             // If the length of this node's edge list is small, the length is stored in the header.
             // If it is not, we fall back to another decoder call.
@@ -242,12 +242,11 @@ impl SerializedDepGraph {
             let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize);
             // The in-memory structure for the edges list stores the byte width of the edges on
             // this node with the offset into the global edge data array.
-            let edges_header = node_header.edges_header(&edge_list_data);
+            let edges_header = node_header.edges_header(&edge_list_data, num_edges);
 
             edge_list_data.extend(d.read_raw_bytes(edges_len_bytes));
 
-            let _i: SerializedDepNodeIndex = edge_list_indices.push(edges_header);
-            debug_assert_eq!(_i.index(), _index);
+            edge_list_indices[index] = edges_header;
         }
 
         // When we access the edge list data, we do a fixed-size read from the edge list data then
@@ -298,9 +297,10 @@ impl SerializedDepGraph {
 /// * In whatever bits remain, the length of the edge list for this node, if it fits
 struct SerializedNodeHeader<D> {
     // 2 bytes for the DepNode
+    // 4 bytes for the index
     // 16 for Fingerprint in DepNode
     // 16 for Fingerprint in NodeInfo
-    bytes: [u8; 34],
+    bytes: [u8; 38],
     _marker: PhantomData<D>,
 }
 
@@ -310,6 +310,7 @@ struct Unpacked {
     len: Option<u32>,
     bytes_per_index: usize,
     kind: DepKind,
+    index: SerializedDepNodeIndex,
     hash: PackedFingerprint,
     fingerprint: Fingerprint,
 }
@@ -331,6 +332,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
     #[inline]
     fn new(
         node: DepNode,
+        index: DepNodeIndex,
         fingerprint: Fingerprint,
         edge_max_index: u32,
         edge_count: usize,
@@ -352,10 +354,11 @@ impl<D: Deps> SerializedNodeHeader<D> {
         let hash: Fingerprint = node.hash.into();
 
         // Using half-open ranges ensures an unconditional panic if we get the magic numbers wrong.
-        let mut bytes = [0u8; 34];
+        let mut bytes = [0u8; 38];
         bytes[..2].copy_from_slice(&head.to_le_bytes());
-        bytes[2..18].copy_from_slice(&hash.to_le_bytes());
-        bytes[18..].copy_from_slice(&fingerprint.to_le_bytes());
+        bytes[2..6].copy_from_slice(&index.as_u32().to_le_bytes());
+        bytes[6..22].copy_from_slice(&hash.to_le_bytes());
+        bytes[22..].copy_from_slice(&fingerprint.to_le_bytes());
 
         #[cfg(debug_assertions)]
         {
@@ -372,8 +375,9 @@ impl<D: Deps> SerializedNodeHeader<D> {
     #[inline]
     fn unpack(&self) -> Unpacked {
         let head = u16::from_le_bytes(self.bytes[..2].try_into().unwrap());
-        let hash = self.bytes[2..18].try_into().unwrap();
-        let fingerprint = self.bytes[18..].try_into().unwrap();
+        let index = u32::from_le_bytes(self.bytes[2..6].try_into().unwrap());
+        let hash = self.bytes[6..22].try_into().unwrap();
+        let fingerprint = self.bytes[22..].try_into().unwrap();
 
         let kind = head & mask(Self::KIND_BITS) as u16;
         let bytes_per_index = (head >> Self::KIND_BITS) & mask(Self::WIDTH_BITS) as u16;
@@ -383,6 +387,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
             len: len.checked_sub(1),
             bytes_per_index: bytes_per_index as usize + 1,
             kind: DepKind::new(kind),
+            index: SerializedDepNodeIndex::from_u32(index),
             hash: Fingerprint::from_le_bytes(hash).into(),
             fingerprint: Fingerprint::from_le_bytes(fingerprint),
         }
@@ -399,6 +404,11 @@ impl<D: Deps> SerializedNodeHeader<D> {
     }
 
     #[inline]
+    fn index(&self) -> SerializedDepNodeIndex {
+        self.unpack().index
+    }
+
+    #[inline]
     fn fingerprint(&self) -> Fingerprint {
         self.unpack().fingerprint
     }
@@ -410,9 +420,10 @@ impl<D: Deps> SerializedNodeHeader<D> {
     }
 
     #[inline]
-    fn edges_header(&self, edge_list_data: &[u8]) -> EdgeHeader {
+    fn edges_header(&self, edge_list_data: &[u8], num_edges: u32) -> EdgeHeader {
         EdgeHeader {
             repr: (edge_list_data.len() << DEP_NODE_WIDTH_BITS) | (self.bytes_per_index() - 1),
+            num_edges,
         }
     }
 }
@@ -425,10 +436,15 @@ struct NodeInfo {
 }
 
 impl NodeInfo {
-    fn encode<D: Deps>(&self, e: &mut FileEncoder) {
+    fn encode<D: Deps>(&self, e: &mut MemEncoder, index: DepNodeIndex) {
         let NodeInfo { node, fingerprint, ref edges } = *self;
-        let header =
-            SerializedNodeHeader::<D>::new(node, fingerprint, edges.max_index(), edges.len());
+        let header = SerializedNodeHeader::<D>::new(
+            node,
+            index,
+            fingerprint,
+            edges.max_index(),
+            edges.len(),
+        );
         e.write_array(header.bytes);
 
         if header.len().is_none() {
@@ -450,8 +466,9 @@ impl NodeInfo {
     /// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`.
     #[inline]
     fn encode_promoted<D: Deps>(
-        e: &mut FileEncoder,
+        e: &mut MemEncoder,
         node: DepNode,
+        index: DepNodeIndex,
         fingerprint: Fingerprint,
         prev_index: SerializedDepNodeIndex,
         colors: &DepNodeColorMap,
@@ -464,7 +481,7 @@ impl NodeInfo {
         let edge_max =
             edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
 
-        let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count);
+        let header = SerializedNodeHeader::<D>::new(node, index, fingerprint, edge_max, edge_count);
         e.write_array(header.bytes);
 
         if header.len().is_none() {
@@ -498,6 +515,8 @@ struct EncoderState<D: Deps> {
     total_edge_count: usize,
     stats: Option<FxHashMap<DepKind, Stat>>,
 
+    mem_encoder: MemEncoder,
+
     /// Stores the number of times we've encoded each dep kind.
     kind_stats: Vec<u32>,
     marker: PhantomData<D>,
@@ -511,22 +530,28 @@ impl<D: Deps> EncoderState<D> {
             total_edge_count: 0,
             total_node_count: 0,
             stats: record_stats.then(FxHashMap::default),
+            mem_encoder: MemEncoder::new(),
             kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(),
             marker: PhantomData,
         }
     }
 
     #[inline]
+    fn alloc_index(&mut self) -> DepNodeIndex {
+        let index = DepNodeIndex::new(self.total_node_count);
+        self.total_node_count += 1;
+        index
+    }
+
+    #[inline]
     fn record(
         &mut self,
         node: DepNode,
+        index: DepNodeIndex,
         edge_count: usize,
         edges: impl FnOnce(&mut Self) -> Vec<DepNodeIndex>,
         record_graph: &Option<Lock<DepGraphQuery>>,
     ) -> DepNodeIndex {
-        let index = DepNodeIndex::new(self.total_node_count);
-
-        self.total_node_count += 1;
         self.kind_stats[node.kind.as_usize()] += 1;
         self.total_edge_count += edge_count;
 
@@ -558,14 +583,25 @@ impl<D: Deps> EncoderState<D> {
         index
     }
 
+    #[inline]
+    fn flush_mem_encoder(&mut self) {
+        let data = &mut self.mem_encoder.data;
+        if data.len() > 64 * 1024 {
+            self.encoder.emit_raw_bytes(&data[..]);
+            data.clear();
+        }
+    }
+
     /// Encodes a node to the current graph.
     fn encode_node(
         &mut self,
         node: &NodeInfo,
         record_graph: &Option<Lock<DepGraphQuery>>,
     ) -> DepNodeIndex {
-        node.encode::<D>(&mut self.encoder);
-        self.record(node.node, node.edges.len(), |_| node.edges[..].to_vec(), record_graph)
+        let index = self.alloc_index();
+        node.encode::<D>(&mut self.mem_encoder, index);
+        self.flush_mem_encoder();
+        self.record(node.node, index, node.edges.len(), |_| node.edges[..].to_vec(), record_graph)
     }
 
     /// Encodes a node that was promoted from the previous graph. It reads the information directly from
@@ -581,20 +617,22 @@ impl<D: Deps> EncoderState<D> {
         record_graph: &Option<Lock<DepGraphQuery>>,
         colors: &DepNodeColorMap,
     ) -> DepNodeIndex {
+        let index = self.alloc_index();
         let node = self.previous.index_to_node(prev_index);
-
         let fingerprint = self.previous.fingerprint_by_index(prev_index);
         let edge_count = NodeInfo::encode_promoted::<D>(
-            &mut self.encoder,
+            &mut self.mem_encoder,
             node,
+            index,
             fingerprint,
             prev_index,
             colors,
             &self.previous,
         );
-
+        self.flush_mem_encoder();
         self.record(
             node,
+            index,
             edge_count,
             |this| {
                 this.previous
@@ -603,12 +641,14 @@ impl<D: Deps> EncoderState<D> {
                     .collect()
             },
             record_graph,
-        )
+        );
+        index
     }
 
     fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
         let Self {
             mut encoder,
+            mem_encoder,
             total_node_count,
             total_edge_count,
             stats: _,
@@ -617,6 +657,8 @@ impl<D: Deps> EncoderState<D> {
             previous,
         } = self;
 
+        encoder.emit_raw_bytes(&mem_encoder.data);
+
         let node_count = total_node_count.try_into().unwrap();
         let edge_count = total_edge_count.try_into().unwrap();
 
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index 2aedd365adc..b159b876c7e 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -1,9 +1,9 @@
 // tidy-alphabetical-start
 #![allow(rustc::potential_query_instability, internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
-#![feature(let_chains)]
 #![feature(min_specialization)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b121755acd9..4a252a7b528 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -10,13 +10,13 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs
index e4792563e71..729c921450e 100644
--- a/compiler/rustc_sanitizers/src/lib.rs
+++ b/compiler/rustc_sanitizers/src/lib.rs
@@ -4,7 +4,7 @@
 //! compiler.
 
 // tidy-alphabetical-start
-#![feature(let_chains)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 // tidy-alphabetical-end
 
 pub mod cfi;
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 0a55504a556..00bad8e70cf 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -10,6 +10,8 @@ use crate::int_overflow::DebugStrictAdd;
 use crate::leb128;
 use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
 
+pub mod mem_encoder;
+
 // -----------------------------------------------------------------------------
 // Encoder
 // -----------------------------------------------------------------------------
diff --git a/compiler/rustc_serialize/src/opaque/mem_encoder.rs b/compiler/rustc_serialize/src/opaque/mem_encoder.rs
new file mode 100644
index 00000000000..56beebb49af
--- /dev/null
+++ b/compiler/rustc_serialize/src/opaque/mem_encoder.rs
@@ -0,0 +1,128 @@
+use super::IntEncodedWithFixedSize;
+use crate::{Encodable, Encoder, leb128};
+
+pub struct MemEncoder {
+    pub data: Vec<u8>,
+}
+
+impl MemEncoder {
+    pub fn new() -> MemEncoder {
+        MemEncoder { data: vec![] }
+    }
+
+    #[inline]
+    pub fn position(&self) -> usize {
+        self.data.len()
+    }
+
+    pub fn finish(self) -> Vec<u8> {
+        self.data
+    }
+
+    /// Write up to `N` bytes to this encoder.
+    ///
+    /// This function can be used to avoid the overhead of calling memcpy for writes that
+    /// have runtime-variable length, but are small and have a small fixed upper bound.
+    ///
+    /// This can be used to do in-place encoding as is done for leb128 (without this function
+    /// we would need to write to a temporary buffer then memcpy into the encoder), and it can
+    /// also be used to implement the varint scheme we use for rmeta and dep graph encoding,
+    /// where we only want to encode the first few bytes of an integer. Note that common
+    /// architectures support fixed-size writes up to 8 bytes with one instruction, so while this
+    /// does in some sense do wasted work, we come out ahead.
+    #[inline]
+    pub fn write_with<const N: usize>(&mut self, visitor: impl FnOnce(&mut [u8; N]) -> usize) {
+        self.data.reserve(N);
+
+        let old_len = self.data.len();
+
+        // SAFETY: The above `reserve` ensures that there is enough
+        // room to write the encoded value to the vector's internal buffer.
+        // The memory is also initialized as 0.
+        let buf = unsafe {
+            let buf = self.data.as_mut_ptr().add(old_len) as *mut [u8; N];
+            *buf = [0; N];
+            &mut *buf
+        };
+        let written = visitor(buf);
+        if written > N {
+            Self::panic_invalid_write::<N>(written);
+        }
+        unsafe { self.data.set_len(old_len + written) };
+    }
+
+    #[cold]
+    #[inline(never)]
+    fn panic_invalid_write<const N: usize>(written: usize) {
+        panic!("MemEncoder::write_with::<{N}> cannot be used to write {written} bytes");
+    }
+
+    /// Helper for calls where [`MemEncoder::write_with`] always writes the whole array.
+    #[inline]
+    pub fn write_array<const N: usize>(&mut self, buf: [u8; N]) {
+        self.write_with(|dest| {
+            *dest = buf;
+            N
+        })
+    }
+}
+
+macro_rules! write_leb128 {
+    ($this_fn:ident, $int_ty:ty, $write_leb_fn:ident) => {
+        #[inline]
+        fn $this_fn(&mut self, v: $int_ty) {
+            self.write_with(|buf| leb128::$write_leb_fn(buf, v))
+        }
+    };
+}
+
+impl Encoder for MemEncoder {
+    write_leb128!(emit_usize, usize, write_usize_leb128);
+    write_leb128!(emit_u128, u128, write_u128_leb128);
+    write_leb128!(emit_u64, u64, write_u64_leb128);
+    write_leb128!(emit_u32, u32, write_u32_leb128);
+
+    #[inline]
+    fn emit_u16(&mut self, v: u16) {
+        self.write_array(v.to_le_bytes());
+    }
+
+    #[inline]
+    fn emit_u8(&mut self, v: u8) {
+        self.write_array([v]);
+    }
+
+    write_leb128!(emit_isize, isize, write_isize_leb128);
+    write_leb128!(emit_i128, i128, write_i128_leb128);
+    write_leb128!(emit_i64, i64, write_i64_leb128);
+    write_leb128!(emit_i32, i32, write_i32_leb128);
+
+    #[inline]
+    fn emit_i16(&mut self, v: i16) {
+        self.write_array(v.to_le_bytes());
+    }
+
+    #[inline]
+    fn emit_raw_bytes(&mut self, s: &[u8]) {
+        self.data.extend_from_slice(s);
+    }
+}
+
+// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
+// since the default implementations call `encode` on their slices internally.
+impl Encodable<MemEncoder> for [u8] {
+    fn encode(&self, e: &mut MemEncoder) {
+        Encoder::emit_usize(e, self.len());
+        e.emit_raw_bytes(self);
+    }
+}
+
+impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
+    #[inline]
+    fn encode(&self, e: &mut MemEncoder) {
+        let start_pos = e.position();
+        e.write_array(self.0.to_le_bytes());
+        let end_pos = e.position();
+        debug_assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
+    }
+}
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 231ca434962..cbfe9e0da6a 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -142,6 +142,10 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
             | (sym::target_has_atomic, Some(_))
             | (sym::target_has_atomic_equal_alignment, Some(_))
             | (sym::target_has_atomic_load_store, Some(_))
+            | (sym::target_has_reliable_f16, None | Some(_))
+            | (sym::target_has_reliable_f16_math, None | Some(_))
+            | (sym::target_has_reliable_f128, None | Some(_))
+            | (sym::target_has_reliable_f128_math, None | Some(_))
             | (sym::target_thread_local, None) => disallow(cfg, "--target"),
             (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
             (sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 0e19b982a13..ec8e9898dc7 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,8 +1,8 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(default_field_values)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(rustc_attrs)]
 // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
 // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f788fd48037..fccdaed21a2 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -17,6 +17,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
@@ -24,7 +25,6 @@
 #![feature(core_io_borrowed_buf)]
 #![feature(hash_set_entry)]
 #![feature(if_let_guard)]
-#![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(negative_impls)]
 #![feature(read_buf)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9ddeef6c462..31b85677997 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -623,6 +623,7 @@ symbols! {
         cfg_target_feature,
         cfg_target_has_atomic,
         cfg_target_has_atomic_equal_alignment,
+        cfg_target_has_reliable_f16_f128,
         cfg_target_thread_local,
         cfg_target_vendor,
         cfg_trace: "<cfg>", // must not be a valid identifier
@@ -2074,6 +2075,10 @@ symbols! {
         target_has_atomic,
         target_has_atomic_equal_alignment,
         target_has_atomic_load_store,
+        target_has_reliable_f128,
+        target_has_reliable_f128_math,
+        target_has_reliable_f16,
+        target_has_reliable_f16_math,
         target_os,
         target_pointer_width,
         target_thread_local,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index cc33974cc62..ca8918e06aa 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -89,9 +89,9 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
-#![feature(let_chains)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index df99280f571..922c18448d5 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -9,12 +9,12 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(debug_closure_helpers)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 54544a90226..595dd12d6f6 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1523,19 +1523,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     return None;
                 };
 
-                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_term.def_id)?;
-                let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-
                 let mut associated_items = vec![];
                 self.tcx.for_each_relevant_impl(
                     self.tcx.trait_of_item(proj.projection_term.def_id)?,
                     proj.projection_term.self_ty(),
                     |impl_def_id| {
                         associated_items.extend(
-                            self.tcx
-                                .associated_items(impl_def_id)
-                                .in_definition_order()
-                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
+                            self.tcx.associated_items(impl_def_id).in_definition_order().find(
+                                |assoc| {
+                                    assoc.trait_item_def_id == Some(proj.projection_term.def_id)
+                                },
+                            ),
                         );
                     },
                 );
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 93c11805304..7613a0cef52 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -14,6 +14,7 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -23,7 +24,6 @@
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(iterator_try_reduce)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 57051e0df55..ea0f6b8dfba 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(bootstrap, feature(let_chains))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
@@ -13,7 +14,6 @@
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iterator_try_collect)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 417803e75ea..9b066b6869f 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -442,6 +442,14 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
 {
     fn as_clause(self) -> Option<I::Clause>;
 
+    fn as_normalizes_to(self) -> Option<ty::Binder<I, ty::NormalizesTo<I>>> {
+        let kind = self.kind();
+        match kind.skip_binder() {
+            ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)),
+            _ => None,
+        }
+    }
+
     // FIXME: Eventually uplift the impl out of rustc and make this defaulted.
     fn allow_normalization(self) -> bool;
 }
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 330b4098764..16c0c118040 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1138,6 +1138,10 @@ pub(crate) mod builtin {
         issue = "29599",
         reason = "`concat_idents` is not stable enough for use and is subject to change"
     )]
+    #[deprecated(
+        since = "1.88.0",
+        note = "use `${concat(...)}` with the `macro_metavar_expr_concat` feature instead"
+    )]
     #[rustc_builtin_macro]
     #[macro_export]
     macro_rules! concat_idents {
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 7ec0ac71271..aed5a043c11 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -162,8 +162,14 @@
 //! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`]
 //! is [`Some`] or [`None`], respectively.
 //!
+//! The [`is_some_and`] and [`is_none_or`] methods apply the provided function
+//! to the contents of the [`Option`] to produce a boolean value.
+//! If this is [`None`] then a default result is returned instead without executing the function.
+//!
 //! [`is_none`]: Option::is_none
 //! [`is_some`]: Option::is_some
+//! [`is_some_and`]: Option::is_some_and
+//! [`is_none_or`]: Option::is_none_or
 //!
 //! ## Adapters for working with references
 //!
@@ -177,6 +183,10 @@
 //!   <code>[Option]<[Pin]<[&]T>></code>
 //! * [`as_pin_mut`] converts from <code>[Pin]<[&mut] [Option]\<T>></code> to
 //!   <code>[Option]<[Pin]<[&mut] T>></code>
+//! * [`as_slice`] returns a one-element slice of the contained value, if any.
+//!   If this is [`None`], an empty slice is returned.
+//! * [`as_mut_slice`] returns a mutable one-element slice of the contained value, if any.
+//!   If this is [`None`], an empty slice is returned.
 //!
 //! [&]: reference "shared reference"
 //! [&mut]: reference "mutable reference"
@@ -187,6 +197,8 @@
 //! [`as_pin_mut`]: Option::as_pin_mut
 //! [`as_pin_ref`]: Option::as_pin_ref
 //! [`as_ref`]: Option::as_ref
+//! [`as_slice`]: Option::as_slice
+//! [`as_mut_slice`]: Option::as_mut_slice
 //!
 //! ## Extracting the contained value
 //!
@@ -200,12 +212,15 @@
 //!   (which must implement the [`Default`] trait)
 //! * [`unwrap_or_else`] returns the result of evaluating the provided
 //!   function
+//! * [`unwrap_unchecked`] produces *[undefined behavior]*
 //!
 //! [`expect`]: Option::expect
 //! [`unwrap`]: Option::unwrap
 //! [`unwrap_or`]: Option::unwrap_or
 //! [`unwrap_or_default`]: Option::unwrap_or_default
 //! [`unwrap_or_else`]: Option::unwrap_or_else
+//! [`unwrap_unchecked`]: Option::unwrap_unchecked
+//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
 //!
 //! ## Transforming contained values
 //!
@@ -230,8 +245,9 @@
 //! * [`filter`] calls the provided predicate function on the contained
 //!   value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`]
 //!   if the function returns `true`; otherwise, returns [`None`]
-//! * [`flatten`] removes one level of nesting from an
-//!   [`Option<Option<T>>`]
+//! * [`flatten`] removes one level of nesting from an [`Option<Option<T>>`]
+//! * [`inspect`] method takes ownership of the [`Option`] and applies
+//!   the provided function to the contained value by reference if [`Some`]
 //! * [`map`] transforms [`Option<T>`] to [`Option<U>`] by applying the
 //!   provided function to the contained value of [`Some`] and leaving
 //!   [`None`] values unchanged
@@ -239,6 +255,7 @@
 //! [`Some(t)`]: Some
 //! [`filter`]: Option::filter
 //! [`flatten`]: Option::flatten
+//! [`inspect`]: Option::inspect
 //! [`map`]: Option::map
 //!
 //! These methods transform [`Option<T>`] to a value of a possibly
@@ -621,6 +638,10 @@ impl<T> Option<T> {
     ///
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_some_and(|x| x > 1), false);
+    ///
+    /// let x: Option<String> = Some("ownership".to_string());
+    /// assert_eq!(x.as_ref().is_some_and(|x| x.len() > 1), true);
+    /// println!("still alive {:?}", x);
     /// ```
     #[must_use]
     #[inline]
@@ -665,6 +686,10 @@ impl<T> Option<T> {
     ///
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_none_or(|x| x > 1), true);
+    ///
+    /// let x: Option<String> = Some("ownership".to_string());
+    /// assert_eq!(x.as_ref().is_none_or(|x| x.len() > 1), true);
+    /// println!("still alive {:?}", x);
     /// ```
     #[must_use]
     #[inline]
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 8f1b5275871..9737d0baec7 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -59,6 +59,7 @@ pub use crate::hash::macros::Hash;
 
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 #[doc(no_inline)]
 pub use crate::{
     assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 48ab9267f21..736ffb7d0ca 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -259,8 +259,14 @@
 //! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`]
 //! is [`Ok`] or [`Err`], respectively.
 //!
+//! The [`is_ok_and`] and [`is_err_and`] methods apply the provided function
+//! to the contents of the [`Result`] to produce a boolean value. If the [`Result`] does not have the expected variant
+//! then [`false`] is returned instead without executing the function.
+//!
 //! [`is_err`]: Result::is_err
 //! [`is_ok`]: Result::is_ok
+//! [`is_ok_and`]: Result::is_ok_and
+//! [`is_err_and`]: Result::is_err_and
 //!
 //! ## Adapters for working with references
 //!
@@ -287,6 +293,7 @@
 //!   (which must implement the [`Default`] trait)
 //! * [`unwrap_or_else`] returns the result of evaluating the provided
 //!   function
+//! * [`unwrap_unchecked`] produces *[undefined behavior]*
 //!
 //! The panicking methods [`expect`] and [`unwrap`] require `E` to
 //! implement the [`Debug`] trait.
@@ -297,6 +304,8 @@
 //! [`unwrap_or`]: Result::unwrap_or
 //! [`unwrap_or_default`]: Result::unwrap_or_default
 //! [`unwrap_or_else`]: Result::unwrap_or_else
+//! [`unwrap_unchecked`]: Result::unwrap_unchecked
+//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
 //!
 //! These methods extract the contained value in a [`Result<T, E>`] when it
 //! is the [`Err`] variant. They require `T` to implement the [`Debug`]
@@ -304,10 +313,13 @@
 //!
 //! * [`expect_err`] panics with a provided custom message
 //! * [`unwrap_err`] panics with a generic message
+//! * [`unwrap_err_unchecked`] produces *[undefined behavior]*
 //!
 //! [`Debug`]: crate::fmt::Debug
 //! [`expect_err`]: Result::expect_err
 //! [`unwrap_err`]: Result::unwrap_err
+//! [`unwrap_err_unchecked`]: Result::unwrap_err_unchecked
+//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
 //!
 //! ## Transforming contained values
 //!
@@ -330,21 +342,29 @@
 //! [`Some(v)`]: Option::Some
 //! [`transpose`]: Result::transpose
 //!
-//! This method transforms the contained value of the [`Ok`] variant:
+//! These methods transform the contained value of the [`Ok`] variant:
 //!
 //! * [`map`] transforms [`Result<T, E>`] into [`Result<U, E>`] by applying
 //!   the provided function to the contained value of [`Ok`] and leaving
 //!   [`Err`] values unchanged
+//! * [`inspect`] takes ownership of the [`Result`], applies the
+//!   provided function to the contained value by reference,
+//!   and then returns the [`Result`]
 //!
 //! [`map`]: Result::map
+//! [`inspect`]: Result::inspect
 //!
-//! This method transforms the contained value of the [`Err`] variant:
+//! These methods transform the contained value of the [`Err`] variant:
 //!
 //! * [`map_err`] transforms [`Result<T, E>`] into [`Result<T, F>`] by
 //!   applying the provided function to the contained value of [`Err`] and
 //!   leaving [`Ok`] values unchanged
+//! * [`inspect_err`] takes ownership of the [`Result`], applies the
+//!   provided function to the contained value of [`Err`] by reference,
+//!   and then returns the [`Result`]
 //!
 //! [`map_err`]: Result::map_err
+//! [`inspect_err`]: Result::inspect_err
 //!
 //! These methods transform a [`Result<T, E>`] into a value of a possibly
 //! different type `U`:
@@ -578,6 +598,10 @@ impl<T, E> Result<T, E> {
     ///
     /// let x: Result<u32, &str> = Err("hey");
     /// assert_eq!(x.is_ok_and(|x| x > 1), false);
+    ///
+    /// let x: Result<String, &str> = Ok("ownership".to_string());
+    /// assert_eq!(x.as_ref().is_ok_and(|x| x.len() > 1), true);
+    /// println!("still alive {:?}", x);
     /// ```
     #[must_use]
     #[inline]
@@ -623,6 +647,10 @@ impl<T, E> Result<T, E> {
     ///
     /// let x: Result<u32, Error> = Ok(123);
     /// assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);
+    ///
+    /// let x: Result<u32, String> = Err("ownership".to_string());
+    /// assert_eq!(x.as_ref().is_err_and(|x| x.len() > 1), true);
+    /// println!("still alive {:?}", x);
     /// ```
     #[must_use]
     #[inline]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 3536e84d58b..7b8f2dd46d6 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -163,4 +163,10 @@ check-cfg = [
     # and to the `backtrace` crate which messes-up with Cargo list
     # of declared features, we therefor expect any feature cfg
     'cfg(feature, values(any()))',
+    # Internal features aren't marked known config by default, we use these to
+    # gate tests.
+    'cfg(target_has_reliable_f16)',
+    'cfg(target_has_reliable_f16_math)',
+    'cfg(target_has_reliable_f128)',
+    'cfg(target_has_reliable_f128_math)',
 ]
diff --git a/library/std/build.rs b/library/std/build.rs
index 40a56d4930d..ef695601a44 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -7,12 +7,6 @@ fn main() {
     let target_vendor =
         env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
     let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
-    let target_abi = env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set");
-    let target_pointer_width: u32 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
-        .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
-        .parse()
-        .unwrap();
-    let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
 
     println!("cargo:rustc-check-cfg=cfg(netbsd10)");
     if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
@@ -80,108 +74,4 @@ fn main() {
     println!("cargo:rustc-cfg=backtrace_in_libstd");
 
     println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
-
-    // Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs,
-    // missing symbols, or other problems, to determine when tests get run.
-    // If more broken platforms are found, please update the tracking issue at
-    // <https://github.com/rust-lang/rust/issues/116909>
-    //
-    // Some of these match arms are redundant; the goal is to separate reasons that the type is
-    // unreliable, even when multiple reasons might fail the same platform.
-    println!("cargo:rustc-check-cfg=cfg(reliable_f16)");
-    println!("cargo:rustc-check-cfg=cfg(reliable_f128)");
-
-    // This is a step beyond only having the types and basic functions available. Math functions
-    // aren't consistently available or correct.
-    println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)");
-    println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)");
-
-    let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) {
-        // We can always enable these in Miri as that is not affected by codegen bugs.
-        _ if is_miri => true,
-        // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
-        ("s390x", _) => false,
-        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
-        ("arm64ec", _) => false,
-        // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
-        ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
-        // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
-        ("csky", _) => false,
-        ("hexagon", _) => false,
-        ("powerpc" | "powerpc64", _) => false,
-        ("sparc" | "sparc64", _) => false,
-        ("wasm32" | "wasm64", _) => false,
-        // `f16` support only requires that symbols converting to and from `f32` are available. We
-        // provide these in `compiler-builtins`, so `f16` should be available on all platforms that
-        // do not have other ABI issues or LLVM crashes.
-        _ => true,
-    };
-
-    let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) {
-        // We can always enable these in Miri as that is not affected by codegen bugs.
-        _ if is_miri => true,
-        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
-        ("arm64ec", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/96432>
-        ("mips64" | "mips64r6", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
-        ("nvptx64", _) => false,
-        // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
-        // list at <https://github.com/rust-lang/rust/issues/116909>)
-        ("powerpc" | "powerpc64", _) => false,
-        // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838>
-        ("sparc", _) => false,
-        // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
-        // not fail if our compiler-builtins is linked.
-        ("x86", _) => false,
-        // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
-        ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
-        // There are no known problems on other platforms, so the only requirement is that symbols
-        // are available. `compiler-builtins` provides all symbols required for core `f128`
-        // support, so this should work for everything else.
-        _ => true,
-    };
-
-    // Configure platforms that have reliable basics but may have unreliable math.
-
-    // LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
-    let has_reliable_f16_math = has_reliable_f16
-        && match (target_arch.as_str(), target_os.as_str()) {
-            // FIXME: Disabled on Miri as the intrinsics are not implemented yet.
-            _ if is_miri => false,
-            // x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
-            ("x86" | "x86_64", _) => false,
-            // Assume that working `f16` means working `f16` math for most platforms, since
-            // operations just go through `f32`.
-            _ => true,
-        };
-
-    let has_reliable_f128_math = has_reliable_f128
-        && match (target_arch.as_str(), target_os.as_str()) {
-            // FIXME: Disabled on Miri as the intrinsics are not implemented yet.
-            _ if is_miri => false,
-            // LLVM lowers `fp128` math to `long double` symbols even on platforms where
-            // `long double` is not IEEE binary128. See
-            // <https://github.com/llvm/llvm-project/issues/44744>.
-            //
-            // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
-            // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
-            // (ld is 80-bit extended precision).
-            ("x86_64", _) => false,
-            (_, "linux") if target_pointer_width == 64 => true,
-            _ => false,
-        };
-
-    if has_reliable_f16 {
-        println!("cargo:rustc-cfg=reliable_f16");
-    }
-    if has_reliable_f128 {
-        println!("cargo:rustc-cfg=reliable_f128");
-    }
-    if has_reliable_f16_math {
-        println!("cargo:rustc-cfg=reliable_f16_math");
-    }
-    if has_reliable_f128_math {
-        println!("cargo:rustc-cfg=reliable_f128_math");
-    }
 }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index c84a72c4fad..1593969e114 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -13,7 +13,7 @@
 use crate::error::Error;
 use crate::ffi::{OsStr, OsString};
 use crate::path::{Path, PathBuf};
-use crate::sys::os as os_imp;
+use crate::sys::{env as env_imp, os as os_imp};
 use crate::{fmt, io, sys};
 
 /// Returns the current working directory as a [`PathBuf`].
@@ -96,7 +96,7 @@ pub struct Vars {
 /// [`env::vars_os()`]: vars_os
 #[stable(feature = "env", since = "1.0.0")]
 pub struct VarsOs {
-    inner: os_imp::Env,
+    inner: env_imp::Env,
 }
 
 /// Returns an iterator of (variable, value) pairs of strings, for all the
@@ -150,7 +150,7 @@ pub fn vars() -> Vars {
 #[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn vars_os() -> VarsOs {
-    VarsOs { inner: os_imp::env() }
+    VarsOs { inner: env_imp::env() }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -259,7 +259,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
 }
 
 fn _var_os(key: &OsStr) -> Option<OsString> {
-    os_imp::getenv(key)
+    env_imp::getenv(key)
 }
 
 /// The error type for operations interacting with environment variables.
@@ -363,7 +363,7 @@ impl Error for VarError {
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
     let (key, value) = (key.as_ref(), value.as_ref());
-    unsafe { os_imp::setenv(key, value) }.unwrap_or_else(|e| {
+    unsafe { env_imp::setenv(key, value) }.unwrap_or_else(|e| {
         panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
     })
 }
@@ -434,7 +434,7 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
     let key = key.as_ref();
-    unsafe { os_imp::unsetenv(key) }
+    unsafe { env_imp::unsetenv(key) }
         .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
 }
 
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 217528fdf1c..2b416b13fa5 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -22,7 +22,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 3.7_f128;
     /// let g = 3.0_f128;
@@ -49,7 +53,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 3.01_f128;
     /// let g = 4.0_f128;
@@ -76,7 +84,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 3.3_f128;
     /// let g = -3.3_f128;
@@ -108,7 +120,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 3.3_f128;
     /// let g = -3.3_f128;
@@ -138,7 +154,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 3.7_f128;
     /// let g = 3.0_f128;
@@ -166,7 +186,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 3.6_f128;
     /// let y = -3.6_f128;
@@ -203,7 +227,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let m = 10.0_f128;
     /// let x = 4.0_f128;
@@ -247,7 +275,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let a: f128 = 7.0;
     /// let b = 4.0;
@@ -289,7 +321,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let a: f128 = 7.0;
     /// let b = 4.0;
@@ -326,7 +362,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 2.0_f128;
     /// let abs_difference = (x.powi(2) - (x * x)).abs();
@@ -354,7 +394,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 2.0_f128;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
@@ -386,7 +430,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let positive = 4.0_f128;
     /// let negative = -4.0_f128;
@@ -417,7 +465,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let one = 1.0f128;
     /// // e^1
@@ -448,7 +500,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 2.0f128;
     ///
@@ -479,7 +535,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let one = 1.0f128;
     /// // e^1
@@ -495,7 +555,11 @@ impl f128 {
     /// Non-positive values:
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// assert_eq!(0_f128.ln(), f128::NEG_INFINITY);
     /// assert!((-42_f128).ln().is_nan());
@@ -526,7 +590,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let five = 5.0f128;
     ///
@@ -540,7 +608,11 @@ impl f128 {
     /// Non-positive values:
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// assert_eq!(0_f128.log(10.0), f128::NEG_INFINITY);
     /// assert!((-42_f128).log(10.0).is_nan());
@@ -567,7 +639,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let two = 2.0f128;
     ///
@@ -581,7 +657,11 @@ impl f128 {
     /// Non-positive values:
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// assert_eq!(0_f128.log2(), f128::NEG_INFINITY);
     /// assert!((-42_f128).log2().is_nan());
@@ -608,7 +688,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let ten = 10.0f128;
     ///
@@ -622,7 +706,11 @@ impl f128 {
     /// Non-positive values:
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// assert_eq!(0_f128.log10(), f128::NEG_INFINITY);
     /// assert!((-42_f128).log10().is_nan());
@@ -651,7 +739,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 8.0f128;
     ///
@@ -687,7 +779,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 2.0f128;
     /// let y = 3.0f128;
@@ -717,7 +813,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = std::f128::consts::FRAC_PI_2;
     ///
@@ -745,7 +845,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 2.0 * std::f128::consts::PI;
     ///
@@ -776,7 +880,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = std::f128::consts::FRAC_PI_4;
     /// let abs_difference = (x.tan() - 1.0).abs();
@@ -808,7 +916,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = std::f128::consts::FRAC_PI_2;
     ///
@@ -843,7 +955,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = std::f128::consts::FRAC_PI_4;
     ///
@@ -877,7 +993,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let f = 1.0f128;
     ///
@@ -915,7 +1035,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// // Positive angles measured counter-clockwise
     /// // from positive x axis
@@ -957,7 +1081,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = std::f128::consts::FRAC_PI_4;
     /// let f = x.sin_cos();
@@ -992,7 +1120,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 1e-8_f128;
     ///
@@ -1028,7 +1160,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 1e-8_f128;
     ///
@@ -1043,7 +1179,11 @@ impl f128 {
     /// Out-of-range values:
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// assert_eq!((-1.0_f128).ln_1p(), f128::NEG_INFINITY);
     /// assert!((-2.0_f128).ln_1p().is_nan());
@@ -1072,7 +1212,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let e = std::f128::consts::E;
     /// let x = 1.0f128;
@@ -1107,7 +1251,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let e = std::f128::consts::E;
     /// let x = 1.0f128;
@@ -1142,7 +1290,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let e = std::f128::consts::E;
     /// let x = 1.0f128;
@@ -1174,7 +1326,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 1.0f128;
     /// let f = x.sinh().asinh();
@@ -1206,7 +1362,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 1.0f128;
     /// let f = x.cosh().acosh();
@@ -1240,7 +1400,11 @@ impl f128 {
     ///
     /// ```
     /// #![feature(f128)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let e = std::f128::consts::E;
     /// let f = e.tanh().atanh();
@@ -1274,7 +1438,11 @@ impl f128 {
     /// ```
     /// #![feature(f128)]
     /// #![feature(float_gamma)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 5.0f128;
     ///
@@ -1309,7 +1477,11 @@ impl f128 {
     /// ```
     /// #![feature(f128)]
     /// #![feature(float_gamma)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     ///
     /// let x = 2.0f128;
     ///
@@ -1344,7 +1516,11 @@ impl f128 {
     /// ```
     /// #![feature(f128)]
     /// #![feature(float_erf)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     /// /// The error function relates what percent of a normal distribution lies
     /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
     /// fn within_standard_deviations(x: f128) -> f128 {
@@ -1383,7 +1559,11 @@ impl f128 {
     /// ```
     /// #![feature(f128)]
     /// #![feature(float_erf)]
-    /// # #[cfg(reliable_f128_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
     /// let x: f128 = 0.123;
     ///
     /// let one = x.erf() + x.erfc();
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index 4dadcbb5185..3f88ab2d400 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -22,7 +22,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 3.7_f16;
     /// let g = 3.0_f16;
@@ -49,7 +53,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 3.01_f16;
     /// let g = 4.0_f16;
@@ -76,7 +84,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 3.3_f16;
     /// let g = -3.3_f16;
@@ -108,7 +120,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 3.3_f16;
     /// let g = -3.3_f16;
@@ -138,7 +154,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 3.7_f16;
     /// let g = 3.0_f16;
@@ -166,7 +186,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 3.6_f16;
     /// let y = -3.6_f16;
@@ -203,7 +227,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let m = 10.0_f16;
     /// let x = 4.0_f16;
@@ -247,7 +275,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let a: f16 = 7.0;
     /// let b = 4.0;
@@ -289,7 +321,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let a: f16 = 7.0;
     /// let b = 4.0;
@@ -326,7 +362,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 2.0_f16;
     /// let abs_difference = (x.powi(2) - (x * x)).abs();
@@ -354,7 +394,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 2.0_f16;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
@@ -386,7 +430,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let positive = 4.0_f16;
     /// let negative = -4.0_f16;
@@ -417,7 +465,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let one = 1.0f16;
     /// // e^1
@@ -448,7 +500,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 2.0f16;
     ///
@@ -479,7 +535,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let one = 1.0f16;
     /// // e^1
@@ -495,7 +555,11 @@ impl f16 {
     /// Non-positive values:
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY);
     /// assert!((-42_f16).ln().is_nan());
@@ -526,7 +590,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let five = 5.0f16;
     ///
@@ -540,7 +608,11 @@ impl f16 {
     /// Non-positive values:
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY);
     /// assert!((-42_f16).log(10.0).is_nan());
@@ -567,7 +639,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let two = 2.0f16;
     ///
@@ -581,7 +657,11 @@ impl f16 {
     /// Non-positive values:
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY);
     /// assert!((-42_f16).log2().is_nan());
@@ -608,7 +688,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let ten = 10.0f16;
     ///
@@ -622,7 +706,11 @@ impl f16 {
     /// Non-positive values:
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY);
     /// assert!((-42_f16).log10().is_nan());
@@ -650,7 +738,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 8.0f16;
     ///
@@ -685,7 +777,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 2.0f16;
     /// let y = 3.0f16;
@@ -715,7 +811,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = std::f16::consts::FRAC_PI_2;
     ///
@@ -743,7 +843,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 2.0 * std::f16::consts::PI;
     ///
@@ -774,7 +878,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = std::f16::consts::FRAC_PI_4;
     /// let abs_difference = (x.tan() - 1.0).abs();
@@ -806,7 +914,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = std::f16::consts::FRAC_PI_2;
     ///
@@ -841,7 +953,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = std::f16::consts::FRAC_PI_4;
     ///
@@ -875,7 +991,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let f = 1.0f16;
     ///
@@ -913,7 +1033,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// // Positive angles measured counter-clockwise
     /// // from positive x axis
@@ -955,7 +1079,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = std::f16::consts::FRAC_PI_4;
     /// let f = x.sin_cos();
@@ -990,7 +1118,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 1e-4_f16;
     ///
@@ -1026,7 +1158,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 1e-4_f16;
     ///
@@ -1041,7 +1177,11 @@ impl f16 {
     /// Out-of-range values:
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
     /// assert!((-2.0_f16).ln_1p().is_nan());
@@ -1070,7 +1210,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let e = std::f16::consts::E;
     /// let x = 1.0f16;
@@ -1105,7 +1249,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let e = std::f16::consts::E;
     /// let x = 1.0f16;
@@ -1140,7 +1288,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let e = std::f16::consts::E;
     /// let x = 1.0f16;
@@ -1172,7 +1324,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 1.0f16;
     /// let f = x.sinh().asinh();
@@ -1204,7 +1360,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 1.0f16;
     /// let f = x.cosh().acosh();
@@ -1238,7 +1398,11 @@ impl f16 {
     ///
     /// ```
     /// #![feature(f16)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let e = std::f16::consts::E;
     /// let f = e.tanh().atanh();
@@ -1272,7 +1436,11 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_gamma)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 5.0f16;
     ///
@@ -1307,7 +1475,11 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_gamma)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     ///
     /// let x = 2.0f16;
     ///
@@ -1342,7 +1514,11 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_erf)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     /// /// The error function relates what percent of a normal distribution lies
     /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
     /// fn within_standard_deviations(x: f16) -> f16 {
@@ -1381,7 +1557,11 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_erf)]
-    /// # #[cfg(reliable_f16_math)] {
+    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(not(bootstrap))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
     /// let x: f16 = 0.123;
     ///
     /// let one = x.erf() + x.erfc();
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index c07c391892d..91701576130 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -119,7 +119,7 @@ mod break_keyword {}
 
 #[doc(keyword = "const")]
 //
-/// Compile-time constants, compile-time evaluable functions, and raw pointers.
+/// Compile-time constants, compile-time blocks, compile-time evaluable functions, and raw pointers.
 ///
 /// ## Compile-time constants
 ///
@@ -166,6 +166,12 @@ mod break_keyword {}
 ///
 /// For more detail on `const`, see the [Rust Book] or the [Reference].
 ///
+/// ## Compile-time blocks
+///
+/// The `const` keyword can also be used to define a block of code that is evaluated at compile time.
+/// This is useful for ensuring certain computations are completed before optimizations happen, as well as
+/// before runtime. For more details, see the [Reference][const-blocks].
+///
 /// ## Compile-time evaluable functions
 ///
 /// The other main use of the `const` keyword is in `const fn`. This marks a function as being
@@ -184,6 +190,7 @@ mod break_keyword {}
 /// [pointer primitive]: pointer
 /// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#constants
 /// [Reference]: ../reference/items/constant-items.html
+/// [const-blocks]: ../reference/expressions/block-expr.html#const-blocks
 /// [const-eval]: ../reference/const_eval.html
 mod const_keyword {}
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 3a52b779037..f77bf92a806 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -709,6 +709,7 @@ pub use core::primitive;
 // Re-export built-in macros defined through core.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 pub use core::{
     assert, assert_matches, cfg, column, compile_error, concat, concat_idents, const_format_args,
     env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax,
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index c15d8c40085..68c9ac1e414 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -46,6 +46,7 @@ pub use crate::result::Result::{self, Err, Ok};
 // Re-exported built-in macros
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 #[doc(no_inline)]
 pub use core::prelude::v1::{
     assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs
index 6a37b32d229..0011f55dc14 100644
--- a/library/std/src/sys/args/mod.rs
+++ b/library/std/src/sys/args/mod.rs
@@ -2,6 +2,16 @@
 
 #![forbid(unsafe_op_in_unsafe_fn)]
 
+#[cfg(any(
+    all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
+    target_family = "windows",
+    target_os = "hermit",
+    target_os = "uefi",
+    target_os = "wasi",
+    target_os = "xous",
+))]
+mod common;
+
 cfg_if::cfg_if! {
     if #[cfg(any(
         all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
diff --git a/library/std/src/sys/args/uefi.rs b/library/std/src/sys/args/uefi.rs
index 84406c7f69d..02dada382ef 100644
--- a/library/std/src/sys/args/uefi.rs
+++ b/library/std/src/sys/args/uefi.rs
@@ -1,14 +1,11 @@
 use r_efi::protocols::loaded_image;
 
+pub use super::common::Args;
 use crate::env::current_exe;
 use crate::ffi::OsString;
 use crate::iter::Iterator;
 use crate::sys::pal::helpers;
 
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
 pub fn args() -> Args {
     let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
 
diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs
index c087fd62965..a7b79ad396e 100644
--- a/library/std/src/sys/args/unix.rs
+++ b/library/std/src/sys/args/unix.rs
@@ -5,16 +5,13 @@
 
 #![allow(dead_code)] // runtime init functions not used during testing
 
+pub use super::common::Args;
 use crate::ffi::CStr;
 #[cfg(target_os = "hermit")]
 use crate::os::hermit::ffi::OsStringExt;
 #[cfg(not(target_os = "hermit"))]
 use crate::os::unix::ffi::OsStringExt;
 
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
 /// One-time global initialization.
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
     unsafe { imp::init(argc, argv) }
diff --git a/library/std/src/sys/args/wasi.rs b/library/std/src/sys/args/wasi.rs
index 4795789e4c7..72063a87dc9 100644
--- a/library/std/src/sys/args/wasi.rs
+++ b/library/std/src/sys/args/wasi.rs
@@ -1,12 +1,9 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
+pub use super::common::Args;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::os::wasi::ffi::OsStrExt;
 
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
 /// Returns the command line arguments
 pub fn args() -> Args {
     Args::new(maybe_args().unwrap_or(Vec::new()))
diff --git a/library/std/src/sys/args/windows.rs b/library/std/src/sys/args/windows.rs
index 47f0e5f2d05..81c44fabdcc 100644
--- a/library/std/src/sys/args/windows.rs
+++ b/library/std/src/sys/args/windows.rs
@@ -6,6 +6,7 @@
 #[cfg(test)]
 mod tests;
 
+pub use super::common::Args;
 use crate::ffi::{OsStr, OsString};
 use crate::num::NonZero;
 use crate::os::windows::prelude::*;
@@ -18,10 +19,6 @@ use crate::sys_common::AsInner;
 use crate::sys_common::wstr::WStrUnits;
 use crate::{io, iter, ptr};
 
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
 pub fn args() -> Args {
     // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
     // string so it's safe for `WStrUnits` to use.
diff --git a/library/std/src/sys/args/xous.rs b/library/std/src/sys/args/xous.rs
index 09a47283d65..2010bad14d1 100644
--- a/library/std/src/sys/args/xous.rs
+++ b/library/std/src/sys/args/xous.rs
@@ -1,10 +1,7 @@
+pub use super::common::Args;
 use crate::sys::pal::os::get_application_parameters;
 use crate::sys::pal::os::params::ArgumentList;
 
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
 pub fn args() -> Args {
     let Some(params) = get_application_parameters() else {
         return Args::new(vec![]);
diff --git a/library/std/src/sys/env/common.rs b/library/std/src/sys/env/common.rs
new file mode 100644
index 00000000000..f161ff073f3
--- /dev/null
+++ b/library/std/src/sys/env/common.rs
@@ -0,0 +1,48 @@
+use crate::ffi::OsString;
+use crate::{fmt, vec};
+
+pub struct Env {
+    iter: vec::IntoIter<(OsString, OsString)>,
+}
+
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list()
+            .entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
+        Env { iter: env.into_iter() }
+    }
+
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        EnvStrDebug { slice: self.iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter.as_slice()).finish()
+    }
+}
+
+impl !Send for Env {}
+impl !Sync for Env {}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
diff --git a/library/std/src/sys/env/hermit.rs b/library/std/src/sys/env/hermit.rs
new file mode 100644
index 00000000000..445ecdeb6a3
--- /dev/null
+++ b/library/std/src/sys/env/hermit.rs
@@ -0,0 +1,72 @@
+use core::slice::memchr;
+
+pub use super::common::Env;
+use crate::collections::HashMap;
+use crate::ffi::{CStr, OsStr, OsString, c_char};
+use crate::io;
+use crate::os::hermit::ffi::OsStringExt;
+use crate::sync::Mutex;
+
+static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
+
+pub fn init(env: *const *const c_char) {
+    let mut guard = ENV.lock().unwrap();
+    let map = guard.insert(HashMap::new());
+
+    if env.is_null() {
+        return;
+    }
+
+    unsafe {
+        let mut environ = env;
+        while !(*environ).is_null() {
+            if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                map.insert(key, value);
+            }
+            environ = environ.add(1);
+        }
+    }
+
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        // Strategy (copied from glibc): Variable name and value are separated
+        // by an ASCII equals sign '='. Since a variable name must not be
+        // empty, allow variable names starting with an equals sign. Skip all
+        // malformed lines.
+        if input.is_empty() {
+            return None;
+        }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| {
+            (
+                OsStringExt::from_vec(input[..p].to_vec()),
+                OsStringExt::from_vec(input[p + 1..].to_vec()),
+            )
+        })
+    }
+}
+
+/// Returns a vector of (variable, value) byte-vector pairs for all the
+/// environment variables of the current process.
+pub fn env() -> Env {
+    let guard = ENV.lock().unwrap();
+    let env = guard.as_ref().unwrap();
+
+    let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect();
+
+    Env::new(result)
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    let (k, v) = (k.to_owned(), v.to_owned());
+    ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
+    Ok(())
+}
+
+pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
+    ENV.lock().unwrap().as_mut().unwrap().remove(k);
+    Ok(())
+}
diff --git a/library/std/src/sys/env/mod.rs b/library/std/src/sys/env/mod.rs
new file mode 100644
index 00000000000..d81ff875c83
--- /dev/null
+++ b/library/std/src/sys/env/mod.rs
@@ -0,0 +1,48 @@
+//! Platform-dependent environment variables abstraction.
+
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+#[cfg(any(
+    target_family = "unix",
+    target_os = "hermit",
+    all(target_vendor = "fortanix", target_env = "sgx"),
+    target_os = "solid_asp3",
+    target_os = "uefi",
+    target_os = "wasi",
+    target_os = "xous",
+))]
+mod common;
+
+cfg_if::cfg_if! {
+    if #[cfg(target_family = "unix")] {
+        mod unix;
+        pub use unix::*;
+    } else if #[cfg(target_family = "windows")] {
+        mod windows;
+        pub use windows::*;
+    } else if #[cfg(target_os = "hermit")] {
+        mod hermit;
+        pub use hermit::*;
+    } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
+        mod sgx;
+        pub use sgx::*;
+    } else if #[cfg(target_os = "solid_asp3")] {
+        mod solid;
+        pub use solid::*;
+    } else if #[cfg(target_os = "uefi")] {
+        mod uefi;
+        pub use uefi::*;
+    } else if #[cfg(target_os = "wasi")] {
+        mod wasi;
+        pub use wasi::*;
+    } else if #[cfg(target_os = "xous")] {
+        mod xous;
+        pub use xous::*;
+    } else if #[cfg(target_os = "zkvm")] {
+        mod zkvm;
+        pub use zkvm::*;
+    } else {
+        mod unsupported;
+        pub use unsupported::*;
+    }
+}
diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs
new file mode 100644
index 00000000000..85be9cd6ad4
--- /dev/null
+++ b/library/std/src/sys/env/sgx.rs
@@ -0,0 +1,55 @@
+#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
+
+pub use super::common::Env;
+use crate::collections::HashMap;
+use crate::ffi::{OsStr, OsString};
+use crate::io;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::{Mutex, Once};
+
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
+#[cfg_attr(test, linkage = "available_externally")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")]
+static ENV: AtomicUsize = AtomicUsize::new(0);
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
+#[cfg_attr(test, linkage = "available_externally")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")]
+static ENV_INIT: Once = Once::new();
+type EnvStore = Mutex<HashMap<OsString, OsString>>;
+
+fn get_env_store() -> Option<&'static EnvStore> {
+    unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() }
+}
+
+fn create_env_store() -> &'static EnvStore {
+    ENV_INIT.call_once(|| {
+        ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed)
+    });
+    unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) }
+}
+
+pub fn env() -> Env {
+    let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
+        map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
+    };
+
+    let env = get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default();
+    Env::new(env)
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned())
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    let (k, v) = (k.to_owned(), v.to_owned());
+    create_env_store().lock().unwrap().insert(k, v);
+    Ok(())
+}
+
+pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
+    if let Some(env) = get_env_store() {
+        env.lock().unwrap().remove(k);
+    }
+    Ok(())
+}
diff --git a/library/std/src/sys/env/solid.rs b/library/std/src/sys/env/solid.rs
new file mode 100644
index 00000000000..ea77fc3c119
--- /dev/null
+++ b/library/std/src/sys/env/solid.rs
@@ -0,0 +1,96 @@
+use core::slice::memchr;
+
+pub use super::common::Env;
+use crate::ffi::{CStr, OsStr, OsString};
+use crate::io;
+use crate::os::raw::{c_char, c_int};
+use crate::os::solid::ffi::{OsStrExt, OsStringExt};
+use crate::sync::{PoisonError, RwLock};
+use crate::sys::common::small_c_string::run_with_cstr;
+
+static ENV_LOCK: RwLock<()> = RwLock::new(());
+
+pub fn env_read_lock() -> impl Drop {
+    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+}
+
+/// Returns a vector of (variable, value) byte-vector pairs for all the
+/// environment variables of the current process.
+pub fn env() -> Env {
+    unsafe extern "C" {
+        static mut environ: *const *const c_char;
+    }
+
+    unsafe {
+        let _guard = env_read_lock();
+        let mut result = Vec::new();
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
+            }
+        }
+        return Env::new(result);
+    }
+
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        // Strategy (copied from glibc): Variable name and value are separated
+        // by an ASCII equals sign '='. Since a variable name must not be
+        // empty, allow variable names starting with an equals sign. Skip all
+        // malformed lines.
+        if input.is_empty() {
+            return None;
+        }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| {
+            (
+                OsStringExt::from_vec(input[..p].to_vec()),
+                OsStringExt::from_vec(input[p + 1..].to_vec()),
+            )
+        })
+    }
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    run_with_cstr(k.as_bytes(), &|k| {
+        let _guard = env_read_lock();
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
+    })
+    .ok()
+    .flatten()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    run_with_cstr(k.as_bytes(), &|k| {
+        run_with_cstr(v.as_bytes(), &|v| {
+            let _guard = ENV_LOCK.write();
+            cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
+        })
+    })
+}
+
+pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
+    run_with_cstr(n.as_bytes(), &|nbuf| {
+        let _guard = ENV_LOCK.write();
+        cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
+    })
+}
+
+/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
+/// function just returns a generic error.
+fn cvt_env(t: c_int) -> io::Result<c_int> {
+    if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) }
+}
diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs
new file mode 100644
index 00000000000..1561df41cac
--- /dev/null
+++ b/library/std/src/sys/env/uefi.rs
@@ -0,0 +1,102 @@
+pub use super::common::Env;
+use crate::ffi::{OsStr, OsString};
+use crate::io;
+
+pub fn env() -> Env {
+    let env = uefi_env::get_all().expect("not supported on this platform");
+    Env::new(env)
+}
+
+pub fn getenv(key: &OsStr) -> Option<OsString> {
+    uefi_env::get(key)
+}
+
+pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
+    uefi_env::set(key, val)
+}
+
+pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
+    uefi_env::unset(key)
+}
+
+mod uefi_env {
+    use crate::ffi::{OsStr, OsString};
+    use crate::io;
+    use crate::os::uefi::ffi::OsStringExt;
+    use crate::ptr::NonNull;
+    use crate::sys::{helpers, unsupported_err};
+
+    pub(crate) fn get(key: &OsStr) -> Option<OsString> {
+        let shell = helpers::open_shell()?;
+        let mut key_ptr = helpers::os_string_to_raw(key)?;
+        unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
+    }
+
+    pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
+        let mut val_ptr = helpers::os_string_to_raw(val)
+            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
+    }
+
+    pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
+    }
+
+    pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+
+        let mut vars = Vec::new();
+        let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
+
+        if val.is_null() {
+            return Ok(vars);
+        }
+
+        let mut start = 0;
+
+        // UEFI Shell returns all keys separated by NULL.
+        // End of string is denoted by two NULLs
+        for i in 0.. {
+            if unsafe { *val.add(i) } == 0 {
+                // Two NULL signal end of string
+                if i == start {
+                    break;
+                }
+
+                let key = OsString::from_wide(unsafe {
+                    crate::slice::from_raw_parts(val.add(start), i - start)
+                });
+                // SAFETY: val.add(start) is always NULL terminated
+                let val = unsafe { get_raw(shell, val.add(start)) }
+                    .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
+
+                vars.push((key, val));
+                start = i + 1;
+            }
+        }
+
+        Ok(vars)
+    }
+
+    unsafe fn get_raw(
+        shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
+        key_ptr: *mut r_efi::efi::Char16,
+    ) -> Option<OsString> {
+        let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
+        helpers::os_string_from_raw(val)
+    }
+
+    unsafe fn set_raw(
+        key_ptr: *mut r_efi::efi::Char16,
+        val_ptr: *mut r_efi::efi::Char16,
+    ) -> io::Result<()> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+        let r =
+            unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
+        if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
+    }
+}
diff --git a/library/std/src/sys/env/unix.rs b/library/std/src/sys/env/unix.rs
new file mode 100644
index 00000000000..78c7af65f9e
--- /dev/null
+++ b/library/std/src/sys/env/unix.rs
@@ -0,0 +1,126 @@
+use core::slice::memchr;
+
+use libc::c_char;
+
+pub use super::common::Env;
+use crate::ffi::{CStr, OsStr, OsString};
+use crate::io;
+use crate::os::unix::prelude::*;
+use crate::sync::{PoisonError, RwLock};
+use crate::sys::common::small_c_string::run_with_cstr;
+use crate::sys::cvt;
+
+// Use `_NSGetEnviron` on Apple platforms.
+//
+// `_NSGetEnviron` is the documented alternative (see `man environ`), and has
+// been available since the first versions of both macOS and iOS.
+//
+// Nowadays, specifically since macOS 10.8, `environ` has been exposed through
+// `libdyld.dylib`, which is linked via. `libSystem.dylib`:
+// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913>
+//
+// So in the end, it likely doesn't really matter which option we use, but the
+// performance cost of using `_NSGetEnviron` is extremely miniscule, and it
+// might be ever so slightly more supported, so let's just use that.
+//
+// NOTE: The header where this is defined (`crt_externs.h`) was added to the
+// iOS 13.0 SDK, which has been the source of a great deal of confusion in the
+// past about the availability of this API.
+//
+// NOTE(madsmtm): Neither this nor using `environ` has been verified to not
+// cause App Store rejections; if this is found to be the case, an alternative
+// implementation of this is possible using `[NSProcessInfo environment]`
+// - which internally uses `_NSGetEnviron` and a system-wide lock on the
+// environment variables to protect against `setenv`, so using that might be
+// desirable anyhow? Though it also means that we have to link to Foundation.
+#[cfg(target_vendor = "apple")]
+pub unsafe fn environ() -> *mut *const *const c_char {
+    unsafe { libc::_NSGetEnviron() as *mut *const *const c_char }
+}
+
+// Use the `environ` static which is part of POSIX.
+#[cfg(not(target_vendor = "apple"))]
+pub unsafe fn environ() -> *mut *const *const c_char {
+    unsafe extern "C" {
+        static mut environ: *const *const c_char;
+    }
+    &raw mut environ
+}
+
+static ENV_LOCK: RwLock<()> = RwLock::new(());
+
+pub fn env_read_lock() -> impl Drop {
+    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+}
+
+/// Returns a vector of (variable, value) byte-vector pairs for all the
+/// environment variables of the current process.
+pub fn env() -> Env {
+    unsafe {
+        let _guard = env_read_lock();
+        let mut environ = *environ();
+        let mut result = Vec::new();
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
+            }
+        }
+        return Env::new(result);
+    }
+
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        // Strategy (copied from glibc): Variable name and value are separated
+        // by an ASCII equals sign '='. Since a variable name must not be
+        // empty, allow variable names starting with an equals sign. Skip all
+        // malformed lines.
+        if input.is_empty() {
+            return None;
+        }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| {
+            (
+                OsStringExt::from_vec(input[..p].to_vec()),
+                OsStringExt::from_vec(input[p + 1..].to_vec()),
+            )
+        })
+    }
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    run_with_cstr(k.as_bytes(), &|k| {
+        let _guard = env_read_lock();
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
+    })
+    .ok()
+    .flatten()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    run_with_cstr(k.as_bytes(), &|k| {
+        run_with_cstr(v.as_bytes(), &|v| {
+            let _guard = ENV_LOCK.write();
+            cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
+        })
+    })
+}
+
+pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
+    run_with_cstr(n.as_bytes(), &|nbuf| {
+        let _guard = ENV_LOCK.write();
+        cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
+    })
+}
diff --git a/library/std/src/sys/env/unsupported.rs b/library/std/src/sys/env/unsupported.rs
new file mode 100644
index 00000000000..98905e64827
--- /dev/null
+++ b/library/std/src/sys/env/unsupported.rs
@@ -0,0 +1,40 @@
+use crate::ffi::{OsStr, OsString};
+use crate::{fmt, io};
+
+pub struct Env(!);
+
+impl Env {
+    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        self.0
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        self.0
+    }
+}
+
+pub fn env() -> Env {
+    panic!("not supported on this platform")
+}
+
+pub fn getenv(_: &OsStr) -> Option<OsString> {
+    None
+}
+
+pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
+    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
+}
+
+pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
+    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
+}
diff --git a/library/std/src/sys/env/wasi.rs b/library/std/src/sys/env/wasi.rs
new file mode 100644
index 00000000000..3719f9db51e
--- /dev/null
+++ b/library/std/src/sys/env/wasi.rs
@@ -0,0 +1,102 @@
+use core::slice::memchr;
+
+pub use super::common::Env;
+use crate::ffi::{CStr, OsStr, OsString};
+use crate::io;
+use crate::os::wasi::prelude::*;
+use crate::sys::common::small_c_string::run_with_cstr;
+use crate::sys::pal::os::{cvt, libc};
+
+cfg_if::cfg_if! {
+    if #[cfg(target_feature = "atomics")] {
+        // Access to the environment must be protected by a lock in multi-threaded scenarios.
+        use crate::sync::{PoisonError, RwLock};
+        static ENV_LOCK: RwLock<()> = RwLock::new(());
+        pub fn env_read_lock() -> impl Drop {
+            ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+        }
+        pub fn env_write_lock() -> impl Drop {
+            ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
+        }
+    } else {
+        // No need for a lock if we are single-threaded.
+        pub fn env_read_lock() -> impl Drop {
+            Box::new(())
+        }
+        pub fn env_write_lock() -> impl Drop {
+            Box::new(())
+        }
+    }
+}
+
+pub fn env() -> Env {
+    unsafe {
+        let _guard = env_read_lock();
+
+        // Use `__wasilibc_get_environ` instead of `environ` here so that we
+        // don't require wasi-libc to eagerly initialize the environment
+        // variables.
+        let mut environ = libc::__wasilibc_get_environ();
+
+        let mut result = Vec::new();
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
+            }
+        }
+        return Env::new(result);
+    }
+
+    // See src/libstd/sys/pal/unix/os.rs, same as that
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        if input.is_empty() {
+            return None;
+        }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| {
+            (
+                OsStringExt::from_vec(input[..p].to_vec()),
+                OsStringExt::from_vec(input[p + 1..].to_vec()),
+            )
+        })
+    }
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    run_with_cstr(k.as_bytes(), &|k| {
+        let _guard = env_read_lock();
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
+    })
+    .ok()
+    .flatten()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    run_with_cstr(k.as_bytes(), &|k| {
+        run_with_cstr(v.as_bytes(), &|v| unsafe {
+            let _guard = env_write_lock();
+            cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
+        })
+    })
+}
+
+pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
+    run_with_cstr(n.as_bytes(), &|nbuf| unsafe {
+        let _guard = env_write_lock();
+        cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
+    })
+}
diff --git a/library/std/src/sys/env/windows.rs b/library/std/src/sys/env/windows.rs
new file mode 100644
index 00000000000..3c4d4a84cfd
--- /dev/null
+++ b/library/std/src/sys/env/windows.rs
@@ -0,0 +1,133 @@
+use crate::ffi::{OsStr, OsString};
+use crate::os::windows::prelude::*;
+use crate::sys::pal::{c, cvt, fill_utf16_buf, to_u16s};
+use crate::{fmt, io, ptr, slice};
+
+pub struct Env {
+    base: *mut c::WCHAR,
+    iter: EnvIterator,
+}
+
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    iter: &'a EnvIterator,
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        let iter: EnvIterator = (*iter).clone();
+        let mut list = f.debug_list();
+        for (a, b) in iter {
+            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
+        }
+        list.finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { base: _, iter } = self;
+        EnvStrDebug { iter }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { base: _, iter } = self;
+        f.debug_list().entries(iter.clone()).finish()
+    }
+}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        let Self { base: _, iter } = self;
+        iter.next()
+    }
+}
+
+#[derive(Clone)]
+struct EnvIterator(*mut c::WCHAR);
+
+impl Iterator for EnvIterator {
+    type Item = (OsString, OsString);
+
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        let Self(cur) = self;
+        loop {
+            unsafe {
+                if **cur == 0 {
+                    return None;
+                }
+                let p = *cur as *const u16;
+                let mut len = 0;
+                while *p.add(len) != 0 {
+                    len += 1;
+                }
+                let s = slice::from_raw_parts(p, len);
+                *cur = cur.add(len + 1);
+
+                // Windows allows environment variables to start with an equals
+                // symbol (in any other position, this is the separator between
+                // variable name and value). Since`s` has at least length 1 at
+                // this point (because the empty string terminates the array of
+                // environment variables), we can safely slice.
+                let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {
+                    Some(p) => p,
+                    None => continue,
+                };
+                return Some((
+                    OsStringExt::from_wide(&s[..pos]),
+                    OsStringExt::from_wide(&s[pos + 1..]),
+                ));
+            }
+        }
+    }
+}
+
+impl Drop for Env {
+    fn drop(&mut self) {
+        unsafe {
+            c::FreeEnvironmentStringsW(self.base);
+        }
+    }
+}
+
+pub fn env() -> Env {
+    unsafe {
+        let ch = c::GetEnvironmentStringsW();
+        if ch.is_null() {
+            panic!("failure getting env string from OS: {}", io::Error::last_os_error());
+        }
+        Env { base: ch, iter: EnvIterator(ch) }
+    }
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    let k = to_u16s(k).ok()?;
+    fill_utf16_buf(
+        |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) },
+        OsStringExt::from_wide,
+    )
+    .ok()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    // SAFETY: We ensure that k and v are null-terminated wide strings.
+    unsafe {
+        let k = to_u16s(k)?;
+        let v = to_u16s(v)?;
+
+        cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
+    }
+}
+
+pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
+    // SAFETY: We ensure that v is a null-terminated wide strings.
+    unsafe {
+        let v = to_u16s(n)?;
+        cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
+    }
+}
diff --git a/library/std/src/sys/env/xous.rs b/library/std/src/sys/env/xous.rs
new file mode 100644
index 00000000000..232a3dafb0b
--- /dev/null
+++ b/library/std/src/sys/env/xous.rs
@@ -0,0 +1,54 @@
+pub use super::common::Env;
+use crate::collections::HashMap;
+use crate::ffi::{OsStr, OsString};
+use crate::io;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::{Mutex, Once};
+use crate::sys::pal::os::{get_application_parameters, params};
+
+static ENV: AtomicUsize = AtomicUsize::new(0);
+static ENV_INIT: Once = Once::new();
+type EnvStore = Mutex<HashMap<OsString, OsString>>;
+
+fn get_env_store() -> &'static EnvStore {
+    ENV_INIT.call_once(|| {
+        let env_store = EnvStore::default();
+        if let Some(params) = get_application_parameters() {
+            for param in params {
+                if let Ok(envs) = params::EnvironmentBlock::try_from(&param) {
+                    let mut env_store = env_store.lock().unwrap();
+                    for env in envs {
+                        env_store.insert(env.key.into(), env.value.into());
+                    }
+                    break;
+                }
+            }
+        }
+        ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed)
+    });
+    unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) }
+}
+
+pub fn env() -> Env {
+    let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
+        map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
+    };
+
+    let env = clone_to_vec(&*get_env_store().lock().unwrap());
+    Env::new(env)
+}
+
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    get_env_store().lock().unwrap().get(k).cloned()
+}
+
+pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    let (k, v) = (k.to_owned(), v.to_owned());
+    get_env_store().lock().unwrap().insert(k, v);
+    Ok(())
+}
+
+pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
+    get_env_store().lock().unwrap().remove(k);
+    Ok(())
+}
diff --git a/library/std/src/sys/env/zkvm.rs b/library/std/src/sys/env/zkvm.rs
new file mode 100644
index 00000000000..2eb7005ba12
--- /dev/null
+++ b/library/std/src/sys/env/zkvm.rs
@@ -0,0 +1,32 @@
+#[expect(dead_code)]
+#[path = "unsupported.rs"]
+mod unsupported_env;
+pub use unsupported_env::{Env, env, setenv, unsetenv};
+
+use crate::ffi::{OsStr, OsString};
+use crate::sys::os_str;
+use crate::sys::pal::{WORD_SIZE, abi};
+use crate::sys_common::FromInner;
+
+pub fn getenv(varname: &OsStr) -> Option<OsString> {
+    let varname = varname.as_encoded_bytes();
+    let nbytes =
+        unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) };
+    if nbytes == usize::MAX {
+        return None;
+    }
+
+    let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE;
+    let words = unsafe { abi::sys_alloc_words(nwords) };
+
+    let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) };
+    debug_assert_eq!(nbytes, nbytes2);
+
+    // Convert to OsString.
+    //
+    // FIXME: We can probably get rid of the extra copy here if we
+    // reimplement "os_str" instead of just using the generic unix
+    // "os_str".
+    let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) };
+    Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() }))
+}
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index e7b631999e0..f9a02b522e5 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -12,6 +12,7 @@ pub mod anonymous_pipe;
 pub mod args;
 pub mod backtrace;
 pub mod cmath;
+pub mod env;
 pub mod env_consts;
 pub mod exit_guard;
 pub mod fd;
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 70636760a83..ea636938d70 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -16,7 +16,10 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 #![allow(missing_docs, nonstandard_style)]
 
+use crate::io::ErrorKind;
+use crate::os::hermit::hermit_abi;
 use crate::os::raw::c_char;
+use crate::sys::env;
 
 pub mod futex;
 pub mod os;
@@ -25,9 +28,6 @@ pub mod pipe;
 pub mod thread;
 pub mod time;
 
-use crate::io::ErrorKind;
-use crate::os::hermit::hermit_abi;
-
 pub fn unsupported<T>() -> crate::io::Result<T> {
     Err(unsupported_err())
 }
@@ -76,7 +76,7 @@ pub unsafe extern "C" fn runtime_entry(
     }
 
     // initialize environment
-    os::init_environment(env);
+    env::init(env);
 
     let result = unsafe { main(argc as isize, argv) };
 
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index 791cdb1e57e..a998c3165e5 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -1,15 +1,10 @@
-use core::slice::memchr;
-
 use super::hermit_abi;
-use crate::collections::HashMap;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, OsStr, OsString, c_char};
+use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
-use crate::os::hermit::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
-use crate::sync::Mutex;
 use crate::sys::unsupported;
-use crate::{fmt, io, str, vec};
+use crate::{fmt, io, str};
 
 pub fn errno() -> i32 {
     unsafe { hermit_abi::get_errno() }
@@ -68,115 +63,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
-
-pub fn init_environment(env: *const *const c_char) {
-    let mut guard = ENV.lock().unwrap();
-    let map = guard.insert(HashMap::new());
-
-    if env.is_null() {
-        return;
-    }
-
-    unsafe {
-        let mut environ = env;
-        while !(*environ).is_null() {
-            if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                map.insert(key, value);
-            }
-            environ = environ.add(1);
-        }
-    }
-
-    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
-        // Strategy (copied from glibc): Variable name and value are separated
-        // by an ASCII equals sign '='. Since a variable name must not be
-        // empty, allow variable names starting with an equals sign. Skip all
-        // malformed lines.
-        if input.is_empty() {
-            return None;
-        }
-        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
-        pos.map(|p| {
-            (
-                OsStringExt::from_vec(input[..p].to_vec()),
-                OsStringExt::from_vec(input[p + 1..].to_vec()),
-            )
-        })
-    }
-}
-
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-/// Returns a vector of (variable, value) byte-vector pairs for all the
-/// environment variables of the current process.
-pub fn env() -> Env {
-    let guard = ENV.lock().unwrap();
-    let env = guard.as_ref().unwrap();
-
-    let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect::<Vec<_>>();
-
-    Env { iter: result.into_iter() }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    let (k, v) = (k.to_owned(), v.to_owned());
-    ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
-    Ok(())
-}
-
-pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
-    ENV.lock().unwrap().as_mut().unwrap().remove(k);
-    Ok(())
-}
-
 pub fn temp_dir() -> PathBuf {
     PathBuf::from("/tmp")
 }
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index 010634cf310..70f838679c9 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -1,14 +1,11 @@
 use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
 
-use crate::collections::HashMap;
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
-use crate::sync::atomic::{AtomicUsize, Ordering};
-use crate::sync::{Mutex, Once};
 use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
-use crate::{fmt, io, str, vec};
+use crate::{fmt, io, str};
 
 pub fn errno() -> i32 {
     RESULT_SUCCESS
@@ -73,101 +70,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
-#[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")]
-static ENV: AtomicUsize = AtomicUsize::new(0);
-// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
-#[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")]
-static ENV_INIT: Once = Once::new();
-type EnvStore = Mutex<HashMap<OsString, OsString>>;
-
-fn get_env_store() -> Option<&'static EnvStore> {
-    unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() }
-}
-
-fn create_env_store() -> &'static EnvStore {
-    ENV_INIT.call_once(|| {
-        ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed)
-    });
-    unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) }
-}
-
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-pub fn env() -> Env {
-    let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
-        map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
-    };
-
-    let iter = get_env_store()
-        .map(|env| clone_to_vec(&env.lock().unwrap()))
-        .unwrap_or_default()
-        .into_iter();
-    Env { iter }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned())
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    let (k, v) = (k.to_owned(), v.to_owned());
-    create_env_store().lock().unwrap().insert(k, v);
-    Ok(())
-}
-
-pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
-    if let Some(env) = get_env_store() {
-        env.lock().unwrap().remove(k);
-    }
-    Ok(())
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem in SGX")
 }
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
index e3b2e0aa50f..8f5976b0592 100644
--- a/library/std/src/sys/pal/solid/os.rs
+++ b/library/std/src/sys/pal/solid/os.rs
@@ -1,14 +1,8 @@
-use core::slice::memchr;
-
 use super::{error, itron, unsupported};
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, OsStr, OsString};
-use crate::os::raw::{c_char, c_int};
-use crate::os::solid::ffi::{OsStrExt, OsStringExt};
+use crate::ffi::{OsStr, OsString};
 use crate::path::{self, PathBuf};
-use crate::sync::{PoisonError, RwLock};
-use crate::sys::common::small_c_string::run_with_cstr;
-use crate::{fmt, io, vec};
+use crate::{fmt, io};
 
 // `solid` directly maps `errno`s to μITRON error codes.
 impl itron::error::ItronError {
@@ -75,138 +69,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-static ENV_LOCK: RwLock<()> = RwLock::new(());
-
-pub fn env_read_lock() -> impl Drop {
-    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
-}
-
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-/// Returns a vector of (variable, value) byte-vector pairs for all the
-/// environment variables of the current process.
-pub fn env() -> Env {
-    unsafe extern "C" {
-        static mut environ: *const *const c_char;
-    }
-
-    unsafe {
-        let _guard = env_read_lock();
-        let mut result = Vec::new();
-        if !environ.is_null() {
-            while !(*environ).is_null() {
-                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                    result.push(key_value);
-                }
-                environ = environ.add(1);
-            }
-        }
-        return Env { iter: result.into_iter() };
-    }
-
-    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
-        // Strategy (copied from glibc): Variable name and value are separated
-        // by an ASCII equals sign '='. Since a variable name must not be
-        // empty, allow variable names starting with an equals sign. Skip all
-        // malformed lines.
-        if input.is_empty() {
-            return None;
-        }
-        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
-        pos.map(|p| {
-            (
-                OsStringExt::from_vec(input[..p].to_vec()),
-                OsStringExt::from_vec(input[p + 1..].to_vec()),
-            )
-        })
-    }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    // environment variables with a nul byte can't be set, so their value is
-    // always None as well
-    run_with_cstr(k.as_bytes(), &|k| {
-        let _guard = env_read_lock();
-        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
-
-        if v.is_null() {
-            Ok(None)
-        } else {
-            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
-            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
-
-            Ok(Some(OsStringExt::from_vec(bytes)))
-        }
-    })
-    .ok()
-    .flatten()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    run_with_cstr(k.as_bytes(), &|k| {
-        run_with_cstr(v.as_bytes(), &|v| {
-            let _guard = ENV_LOCK.write();
-            cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
-        })
-    })
-}
-
-pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
-    run_with_cstr(n.as_bytes(), &|nbuf| {
-        let _guard = ENV_LOCK.write();
-        cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
-    })
-}
-
-/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
-/// function just returns a generic error.
-fn cvt_env(t: c_int) -> io::Result<c_int> {
-    if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) }
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no standard temporary directory on this platform")
 }
diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs
index bf6945811ab..03f3c72b022 100644
--- a/library/std/src/sys/pal/teeos/os.rs
+++ b/library/std/src/sys/pal/teeos/os.rs
@@ -73,47 +73,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub struct Env(!);
-
-impl Env {
-    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-pub fn env() -> Env {
-    panic!("not supported on this platform")
-}
-
-pub fn getenv(_: &OsStr) -> Option<OsString> {
-    None
-}
-
-pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
-}
-
-pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem on this platform")
 }
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index d26d61890c1..bfd4dc81cb4 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -131,60 +131,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     helpers::device_path_to_text(protocol).map(PathBuf::from)
 }
 
-pub struct EnvStrDebug<'a> {
-    iter: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut list = f.debug_list();
-        for (a, b) in self.iter {
-            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
-        }
-        list.finish()
-    }
-}
-
-pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);
-
-impl Env {
-    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        EnvStrDebug { iter: self.0.as_slice() }
-    }
-}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.0.next()
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-pub fn env() -> Env {
-    let env = uefi_env::get_all().expect("not supported on this platform");
-    Env(env.into_iter())
-}
-
-pub fn getenv(key: &OsStr) -> Option<OsString> {
-    uefi_env::get(key)
-}
-
-pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
-    uefi_env::set(key, val)
-}
-
-pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
-    uefi_env::unset(key)
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem on this platform")
 }
@@ -213,85 +159,3 @@ pub fn exit(code: i32) -> ! {
 pub fn getpid() -> u32 {
     panic!("no pids on this platform")
 }
-
-mod uefi_env {
-    use crate::ffi::{OsStr, OsString};
-    use crate::io;
-    use crate::os::uefi::ffi::OsStringExt;
-    use crate::ptr::NonNull;
-    use crate::sys::{helpers, unsupported_err};
-
-    pub(crate) fn get(key: &OsStr) -> Option<OsString> {
-        let shell = helpers::open_shell()?;
-        let mut key_ptr = helpers::os_string_to_raw(key)?;
-        unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
-    }
-
-    pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
-        let mut key_ptr = helpers::os_string_to_raw(key)
-            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
-        let mut val_ptr = helpers::os_string_to_raw(val)
-            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
-        unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
-    }
-
-    pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
-        let mut key_ptr = helpers::os_string_to_raw(key)
-            .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
-        unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
-    }
-
-    pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
-        let shell = helpers::open_shell().ok_or(unsupported_err())?;
-
-        let mut vars = Vec::new();
-        let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
-
-        if val.is_null() {
-            return Ok(vars);
-        }
-
-        let mut start = 0;
-
-        // UEFI Shell returns all keys separated by NULL.
-        // End of string is denoted by two NULLs
-        for i in 0.. {
-            if unsafe { *val.add(i) } == 0 {
-                // Two NULL signal end of string
-                if i == start {
-                    break;
-                }
-
-                let key = OsString::from_wide(unsafe {
-                    crate::slice::from_raw_parts(val.add(start), i - start)
-                });
-                // SAFETY: val.add(start) is always NULL terminated
-                let val = unsafe { get_raw(shell, val.add(start)) }
-                    .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
-
-                vars.push((key, val));
-                start = i + 1;
-            }
-        }
-
-        Ok(vars)
-    }
-
-    unsafe fn get_raw(
-        shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
-        key_ptr: *mut r_efi::efi::Char16,
-    ) -> Option<OsString> {
-        let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
-        helpers::os_string_from_raw(val)
-    }
-
-    unsafe fn set_raw(
-        key_ptr: *mut r_efi::efi::Char16,
-        val_ptr: *mut r_efi::efi::Char16,
-    ) -> io::Result<()> {
-        let shell = helpers::open_shell().ok_or(unsupported_err())?;
-        let r =
-            unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
-        if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
-    }
-}
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index f47421c6705..4883303b88e 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -5,20 +5,15 @@
 #[cfg(test)]
 mod tests;
 
-use core::slice::memchr;
-
 use libc::{c_char, c_int, c_void};
 
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
 use crate::os::unix::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::sync::{PoisonError, RwLock};
-use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
-use crate::sys::weak::weak;
-use crate::sys::{cvt, fd};
-use crate::{fmt, io, iter, mem, ptr, slice, str, vec};
+use crate::sys::common::small_c_string::run_path_with_cstr;
+use crate::sys::cvt;
+use crate::{fmt, io, iter, mem, ptr, slice, str};
 
 const TMPBUF_SZ: usize = 128;
 
@@ -552,166 +547,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     if !path.is_absolute() { getcwd().map(|cwd| cwd.join(path)) } else { Ok(path) }
 }
 
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-// Use `_NSGetEnviron` on Apple platforms.
-//
-// `_NSGetEnviron` is the documented alternative (see `man environ`), and has
-// been available since the first versions of both macOS and iOS.
-//
-// Nowadays, specifically since macOS 10.8, `environ` has been exposed through
-// `libdyld.dylib`, which is linked via. `libSystem.dylib`:
-// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913>
-//
-// So in the end, it likely doesn't really matter which option we use, but the
-// performance cost of using `_NSGetEnviron` is extremely miniscule, and it
-// might be ever so slightly more supported, so let's just use that.
-//
-// NOTE: The header where this is defined (`crt_externs.h`) was added to the
-// iOS 13.0 SDK, which has been the source of a great deal of confusion in the
-// past about the availability of this API.
-//
-// NOTE(madsmtm): Neither this nor using `environ` has been verified to not
-// cause App Store rejections; if this is found to be the case, an alternative
-// implementation of this is possible using `[NSProcessInfo environment]`
-// - which internally uses `_NSGetEnviron` and a system-wide lock on the
-// environment variables to protect against `setenv`, so using that might be
-// desirable anyhow? Though it also means that we have to link to Foundation.
-#[cfg(target_vendor = "apple")]
-pub unsafe fn environ() -> *mut *const *const c_char {
-    libc::_NSGetEnviron() as *mut *const *const c_char
-}
-
-// Use the `environ` static which is part of POSIX.
-#[cfg(not(target_vendor = "apple"))]
-pub unsafe fn environ() -> *mut *const *const c_char {
-    unsafe extern "C" {
-        static mut environ: *const *const c_char;
-    }
-    &raw mut environ
-}
-
-static ENV_LOCK: RwLock<()> = RwLock::new(());
-
-pub fn env_read_lock() -> impl Drop {
-    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
-}
-
-/// Returns a vector of (variable, value) byte-vector pairs for all the
-/// environment variables of the current process.
-pub fn env() -> Env {
-    unsafe {
-        let _guard = env_read_lock();
-        let mut environ = *environ();
-        let mut result = Vec::new();
-        if !environ.is_null() {
-            while !(*environ).is_null() {
-                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                    result.push(key_value);
-                }
-                environ = environ.add(1);
-            }
-        }
-        return Env { iter: result.into_iter() };
-    }
-
-    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
-        // Strategy (copied from glibc): Variable name and value are separated
-        // by an ASCII equals sign '='. Since a variable name must not be
-        // empty, allow variable names starting with an equals sign. Skip all
-        // malformed lines.
-        if input.is_empty() {
-            return None;
-        }
-        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
-        pos.map(|p| {
-            (
-                OsStringExt::from_vec(input[..p].to_vec()),
-                OsStringExt::from_vec(input[p + 1..].to_vec()),
-            )
-        })
-    }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    // environment variables with a nul byte can't be set, so their value is
-    // always None as well
-    run_with_cstr(k.as_bytes(), &|k| {
-        let _guard = env_read_lock();
-        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
-
-        if v.is_null() {
-            Ok(None)
-        } else {
-            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
-            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
-
-            Ok(Some(OsStringExt::from_vec(bytes)))
-        }
-    })
-    .ok()
-    .flatten()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    run_with_cstr(k.as_bytes(), &|k| {
-        run_with_cstr(v.as_bytes(), &|v| {
-            let _guard = ENV_LOCK.write();
-            cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
-        })
-    })
-}
-
-pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
-    run_with_cstr(n.as_bytes(), &|nbuf| {
-        let _guard = ENV_LOCK.write();
-        cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
-    })
-}
-
 #[cfg(not(target_os = "espidf"))]
 pub fn page_size() -> usize {
     unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs
index 73631053e9f..efa6f8d7765 100644
--- a/library/std/src/sys/pal/unix/sync/condvar.rs
+++ b/library/std/src/sys/pal/unix/sync/condvar.rs
@@ -64,7 +64,10 @@ impl Condvar {
         // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
         //
         // To work around this issue, the timeout is clamped to 1000 years.
-        #[cfg(target_vendor = "apple")]
+        //
+        // Cygwin implementation is based on NT API and a super large timeout
+        // makes the syscall block forever.
+        #[cfg(any(target_vendor = "apple", target_os = "cygwin"))]
         let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
 
         let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur);
diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs
index 48de4312885..a8ef97ecf67 100644
--- a/library/std/src/sys/pal/unsupported/os.rs
+++ b/library/std/src/sys/pal/unsupported/os.rs
@@ -62,47 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub struct Env(!);
-
-impl Env {
-    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-pub fn env() -> Env {
-    panic!("not supported on this platform")
-}
-
-pub fn getenv(_: &OsStr) -> Option<OsString> {
-    None
-}
-
-pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
-}
-
-pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem on this platform")
 }
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index ba2b65a1f40..672cf70d1a5 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -1,19 +1,16 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
-use core::slice::memchr;
-
 use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::marker::PhantomData;
-use crate::ops::Drop;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
+use crate::sys::common::small_c_string::run_path_with_cstr;
 use crate::sys::unsupported;
-use crate::{fmt, io, str, vec};
+use crate::{fmt, io, str};
 
 // Add a few symbols not in upstream `libc` just yet.
-mod libc {
+pub mod libc {
     pub use libc::*;
 
     unsafe extern "C" {
@@ -23,28 +20,6 @@ mod libc {
     }
 }
 
-cfg_if::cfg_if! {
-    if #[cfg(target_feature = "atomics")] {
-        // Access to the environment must be protected by a lock in multi-threaded scenarios.
-        use crate::sync::{PoisonError, RwLock};
-        static ENV_LOCK: RwLock<()> = RwLock::new(());
-        pub fn env_read_lock() -> impl Drop {
-            ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
-        }
-        pub fn env_write_lock() -> impl Drop {
-            ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
-        }
-    } else {
-        // No need for a lock if we are single-threaded.
-        pub fn env_read_lock() -> impl Drop {
-            Box::new(())
-        }
-        pub fn env_write_lock() -> impl Drop {
-            Box::new(())
-        }
-    }
-}
-
 pub fn errno() -> i32 {
     unsafe extern "C" {
         #[thread_local]
@@ -141,123 +116,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-pub fn env() -> Env {
-    unsafe {
-        let _guard = env_read_lock();
-
-        // Use `__wasilibc_get_environ` instead of `environ` here so that we
-        // don't require wasi-libc to eagerly initialize the environment
-        // variables.
-        let mut environ = libc::__wasilibc_get_environ();
-
-        let mut result = Vec::new();
-        if !environ.is_null() {
-            while !(*environ).is_null() {
-                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                    result.push(key_value);
-                }
-                environ = environ.add(1);
-            }
-        }
-        return Env { iter: result.into_iter() };
-    }
-
-    // See src/libstd/sys/pal/unix/os.rs, same as that
-    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
-        if input.is_empty() {
-            return None;
-        }
-        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
-        pos.map(|p| {
-            (
-                OsStringExt::from_vec(input[..p].to_vec()),
-                OsStringExt::from_vec(input[p + 1..].to_vec()),
-            )
-        })
-    }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    // environment variables with a nul byte can't be set, so their value is
-    // always None as well
-    run_with_cstr(k.as_bytes(), &|k| {
-        let _guard = env_read_lock();
-        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
-
-        if v.is_null() {
-            Ok(None)
-        } else {
-            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
-            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
-
-            Ok(Some(OsStringExt::from_vec(bytes)))
-        }
-    })
-    .ok()
-    .flatten()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    run_with_cstr(k.as_bytes(), &|k| {
-        run_with_cstr(v.as_bytes(), &|v| unsafe {
-            let _guard = env_write_lock();
-            cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
-        })
-    })
-}
-
-pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
-    run_with_cstr(n.as_bytes(), &|nbuf| unsafe {
-        let _guard = env_write_lock();
-        cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
-    })
-}
-
 #[allow(dead_code)]
 pub fn page_size() -> usize {
     unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
@@ -294,6 +152,6 @@ macro_rules! impl_is_minus_one {
 
 impl_is_minus_one! { i8 i16 i32 i64 isize }
 
-fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
+pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
     if t.is_minus_one() { Err(io::Error::last_os_error()) } else { Ok(t) }
 }
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 044dc2e8cd8..f331282d2d7 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -5,16 +5,16 @@
 #[cfg(test)]
 mod tests;
 
+use super::api;
 #[cfg(not(target_vendor = "uwp"))]
 use super::api::WinError;
-use super::{api, to_u16s};
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::os::windows::ffi::EncodeWide;
 use crate::os::windows::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::sys::{c, cvt};
-use crate::{fmt, io, ptr, slice};
+use crate::sys::pal::{c, cvt};
+use crate::{fmt, io, ptr};
 
 pub fn errno() -> i32 {
     api::get_last_error().code as i32
@@ -76,108 +76,6 @@ pub fn error_string(mut errnum: i32) -> String {
     }
 }
 
-pub struct Env {
-    base: *mut c::WCHAR,
-    iter: EnvIterator,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    iter: &'a EnvIterator,
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        let iter: EnvIterator = (*iter).clone();
-        let mut list = f.debug_list();
-        for (a, b) in iter {
-            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
-        }
-        list.finish()
-    }
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { base: _, iter } = self;
-        EnvStrDebug { iter }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { base: _, iter } = self;
-        f.debug_list().entries(iter.clone()).finish()
-    }
-}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        let Self { base: _, iter } = self;
-        iter.next()
-    }
-}
-
-#[derive(Clone)]
-struct EnvIterator(*mut c::WCHAR);
-
-impl Iterator for EnvIterator {
-    type Item = (OsString, OsString);
-
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        let Self(cur) = self;
-        loop {
-            unsafe {
-                if **cur == 0 {
-                    return None;
-                }
-                let p = *cur as *const u16;
-                let mut len = 0;
-                while *p.add(len) != 0 {
-                    len += 1;
-                }
-                let s = slice::from_raw_parts(p, len);
-                *cur = cur.add(len + 1);
-
-                // Windows allows environment variables to start with an equals
-                // symbol (in any other position, this is the separator between
-                // variable name and value). Since`s` has at least length 1 at
-                // this point (because the empty string terminates the array of
-                // environment variables), we can safely slice.
-                let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {
-                    Some(p) => p,
-                    None => continue,
-                };
-                return Some((
-                    OsStringExt::from_wide(&s[..pos]),
-                    OsStringExt::from_wide(&s[pos + 1..]),
-                ));
-            }
-        }
-    }
-}
-
-impl Drop for Env {
-    fn drop(&mut self) {
-        unsafe {
-            c::FreeEnvironmentStringsW(self.base);
-        }
-    }
-}
-
-pub fn env() -> Env {
-    unsafe {
-        let ch = c::GetEnvironmentStringsW();
-        if ch.is_null() {
-            panic!("failure getting env string from OS: {}", io::Error::last_os_error());
-        }
-        Env { base: ch, iter: EnvIterator(ch) }
-    }
-}
-
 pub struct SplitPaths<'a> {
     data: EncodeWide<'a>,
     must_yield: bool,
@@ -290,33 +188,6 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
     cvt(unsafe { c::SetCurrentDirectoryW(p.as_ptr()) }).map(drop)
 }
 
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    let k = to_u16s(k).ok()?;
-    super::fill_utf16_buf(
-        |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) },
-        OsStringExt::from_wide,
-    )
-    .ok()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    // SAFETY: We ensure that k and v are null-terminated wide strings.
-    unsafe {
-        let k = to_u16s(k)?;
-        let v = to_u16s(v)?;
-
-        cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
-    }
-}
-
-pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
-    // SAFETY: We ensure that v is a null-terminated wide strings.
-    unsafe {
-        let v = to_u16s(n)?;
-        cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
-    }
-}
-
 pub fn temp_dir() -> PathBuf {
     super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
 }
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index 2c87e7d91f2..1b41575358f 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -1,13 +1,11 @@
 use super::unsupported;
-use crate::collections::HashMap;
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::os::xous::ffi::Error as XousError;
 use crate::path::{self, PathBuf};
-use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
-use crate::sync::{Mutex, Once};
-use crate::{fmt, io, vec};
+use crate::sync::atomic::{AtomicPtr, Ordering};
+use crate::{fmt, io};
 
 pub(crate) mod params;
 
@@ -136,100 +134,6 @@ pub(crate) fn get_application_parameters() -> Option<params::ApplicationParamete
     unsafe { params::ApplicationParameters::new_from_ptr(params_address) }
 }
 
-// ---------- Environment handling ---------- //
-static ENV: AtomicUsize = AtomicUsize::new(0);
-static ENV_INIT: Once = Once::new();
-type EnvStore = Mutex<HashMap<OsString, OsString>>;
-
-fn get_env_store() -> &'static EnvStore {
-    ENV_INIT.call_once(|| {
-        let env_store = EnvStore::default();
-        if let Some(params) = get_application_parameters() {
-            for param in params {
-                if let Ok(envs) = params::EnvironmentBlock::try_from(&param) {
-                    let mut env_store = env_store.lock().unwrap();
-                    for env in envs {
-                        env_store.insert(env.key.into(), env.value.into());
-                    }
-                    break;
-                }
-            }
-        }
-        ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed)
-    });
-    unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) }
-}
-
-pub struct Env {
-    iter: vec::IntoIter<(OsString, OsString)>,
-}
-
-// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-pub struct EnvStrDebug<'a> {
-    slice: &'a [(OsString, OsString)],
-}
-
-impl fmt::Debug for EnvStrDebug<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { slice } = self;
-        f.debug_list()
-            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
-            .finish()
-    }
-}
-
-impl Env {
-    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self { iter } = self;
-        EnvStrDebug { slice: iter.as_slice() }
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { iter } = self;
-        f.debug_list().entries(iter.as_slice()).finish()
-    }
-}
-
-impl !Send for Env {}
-impl !Sync for Env {}
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.iter.next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-pub fn env() -> Env {
-    let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
-        map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
-    };
-
-    let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter();
-    Env { iter }
-}
-
-pub fn getenv(k: &OsStr) -> Option<OsString> {
-    get_env_store().lock().unwrap().get(k).cloned()
-}
-
-pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    let (k, v) = (k.to_owned(), v.to_owned());
-    get_env_store().lock().unwrap().insert(k, v);
-    Ok(())
-}
-
-pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
-    get_env_store().lock().unwrap().remove(k);
-    Ok(())
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem on this platform")
 }
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
index 868b19e33b6..a8ef97ecf67 100644
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ b/library/std/src/sys/pal/zkvm/os.rs
@@ -1,10 +1,8 @@
-use super::{WORD_SIZE, abi, unsupported};
+use super::unsupported;
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
-use crate::sys::os_str;
-use crate::sys_common::FromInner;
 use crate::{fmt, io};
 
 pub fn errno() -> i32 {
@@ -64,64 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub struct Env(!);
-
-impl Iterator for Env {
-    type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.0
-    }
-}
-
-pub fn env() -> Env {
-    panic!("not supported on this platform")
-}
-
-impl Env {
-    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-impl fmt::Debug for Env {
-    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self(inner) = self;
-        match *inner {}
-    }
-}
-
-pub fn getenv(varname: &OsStr) -> Option<OsString> {
-    let varname = varname.as_encoded_bytes();
-    let nbytes =
-        unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) };
-    if nbytes == usize::MAX {
-        return None;
-    }
-
-    let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE;
-    let words = unsafe { abi::sys_alloc_words(nwords) };
-
-    let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) };
-    debug_assert_eq!(nbytes, nbytes2);
-
-    // Convert to OsString.
-    //
-    // FIXME: We can probably get rid of the extra copy here if we
-    // reimplement "os_str" instead of just using the generic unix
-    // "os_str".
-    let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) };
-    Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() }))
-}
-
-pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
-}
-
-pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
-}
-
 pub fn temp_dir() -> PathBuf {
     panic!("no filesystem on this platform")
 }
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 92bb809d90c..478f6583b1f 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -88,7 +88,7 @@ impl Command {
         // in its own process. Thus the parent drops the lock guard immediately.
         // The child calls `mem::forget` to leak the lock, which is crucial because
         // releasing a lock is not async-signal-safe.
-        let env_lock = sys::os::env_read_lock();
+        let env_lock = sys::env::env_read_lock();
         let pid = unsafe { self.do_fork()? };
 
         if pid == 0 {
@@ -237,7 +237,7 @@ impl Command {
                     // Similar to when forking, we want to ensure that access to
                     // the environment is synchronized, so make sure to grab the
                     // environment lock before we try to exec.
-                    let _lock = sys::os::env_read_lock();
+                    let _lock = sys::env::env_read_lock();
 
                     let Err(e) = self.do_exec(theirs, envp.as_ref());
                     e
@@ -386,13 +386,13 @@ impl Command {
             impl Drop for Reset {
                 fn drop(&mut self) {
                     unsafe {
-                        *sys::os::environ() = self.0;
+                        *sys::env::environ() = self.0;
                     }
                 }
             }
 
-            _reset = Some(Reset(*sys::os::environ()));
-            *sys::os::environ() = envp.as_ptr();
+            _reset = Some(Reset(*sys::env::environ()));
+            *sys::env::environ() = envp.as_ptr();
         }
 
         libc::execvp(self.get_program_cstr().as_ptr(), self.get_argv().as_ptr());
@@ -739,8 +739,8 @@ impl Command {
             cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
 
             // Make sure we synchronize access to the global `environ` resource
-            let _env_lock = sys::os::env_read_lock();
-            let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
+            let _env_lock = sys::env::env_read_lock();
+            let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::env::environ() as *const _);
 
             #[cfg(not(target_os = "nto"))]
             let spawn_fn = libc::posix_spawnp;
diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs
index 5f1727789a1..b92446f0cf6 100644
--- a/library/std/src/sys/process/unix/vxworks.rs
+++ b/library/std/src/sys/process/unix/vxworks.rs
@@ -67,7 +67,7 @@ impl Command {
             let c_envp = envp
                 .as_ref()
                 .map(|c| c.as_ptr())
-                .unwrap_or_else(|| *sys::os::environ() as *const _);
+                .unwrap_or_else(|| *sys::env::environ() as *const _);
             let stack_size = crate::cmp::max(
                 crate::env::var_os("RUST_MIN_STACK")
                     .and_then(|s| s.to_str().and_then(|s| s.parse().ok()))
@@ -76,7 +76,7 @@ impl Command {
             );
 
             // ensure that access to the environment is synchronized
-            let _lock = sys::os::env_read_lock();
+            let _lock = sys::env::env_read_lock();
 
             let ret = libc::rtpSpawn(
                 self.get_program_cstr().as_ptr(),
diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs
index 677738bac8f..8b13d6e6558 100644
--- a/library/std/tests/floats/f128.rs
+++ b/library/std/tests/floats/f128.rs
@@ -1,9 +1,12 @@
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
-#![cfg(reliable_f128)]
+#![cfg(not(bootstrap))]
+#![cfg(target_has_reliable_f128)]
 
 use std::f128::consts;
 use std::num::FpCategory as Fp;
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 use std::ops::Rem;
 use std::ops::{Add, Div, Mul, Sub};
 
@@ -19,7 +22,9 @@ const TOL: f128 = 1e-12;
 
 /// Tolerances for math that is allowed to be imprecise, usually due to multiple chained
 /// operations.
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 const TOL_IMPR: f128 = 1e-10;
 
 /// Smallest number
@@ -66,8 +71,13 @@ fn test_num_f128() {
     assert_eq!(ten.div(two), ten / two);
 }
 
+// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
+// the intrinsics.
+
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_num_f128_rem() {
     let ten = 10f128;
     let two = 2f128;
@@ -75,28 +85,36 @@ fn test_num_f128_rem() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_min_nan() {
     assert_eq!(f128::NAN.min(2.0), 2.0);
     assert_eq!(2.0f128.min(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_max_nan() {
     assert_eq!(f128::NAN.max(2.0), 2.0);
     assert_eq!(2.0f128.max(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_minimum() {
     assert!(f128::NAN.minimum(2.0).is_nan());
     assert!(2.0f128.minimum(f128::NAN).is_nan());
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_maximum() {
     assert!(f128::NAN.maximum(2.0).is_nan());
     assert!(2.0f128.maximum(f128::NAN).is_nan());
@@ -253,7 +271,9 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_floor() {
     assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
     assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
@@ -268,7 +288,9 @@ fn test_floor() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_ceil() {
     assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
     assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
@@ -283,7 +305,9 @@ fn test_ceil() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_round() {
     assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
     assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
@@ -299,7 +323,9 @@ fn test_round() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_round_ties_even() {
     assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
     assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
@@ -315,7 +341,9 @@ fn test_round_ties_even() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_trunc() {
     assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
     assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
@@ -330,7 +358,9 @@ fn test_trunc() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_fract() {
     assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
     assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
@@ -345,7 +375,9 @@ fn test_fract() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_abs() {
     assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
     assert_eq!(1f128.abs(), 1f128);
@@ -445,7 +477,9 @@ fn test_next_down() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_mul_add() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -462,7 +496,9 @@ fn test_mul_add() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_recip() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -484,7 +520,9 @@ fn test_recip() {
 // Many math functions allow for less accurate results, so the next tolerance up is used
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_powi() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -499,7 +537,9 @@ fn test_powi() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_powf() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -516,7 +556,9 @@ fn test_powf() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_sqrt_domain() {
     assert!(f128::NAN.sqrt().is_nan());
     assert!(f128::NEG_INFINITY.sqrt().is_nan());
@@ -528,7 +570,9 @@ fn test_sqrt_domain() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_exp() {
     assert_eq!(1.0, 0.0f128.exp());
     assert_approx_eq!(consts::E, 1.0f128.exp(), TOL);
@@ -543,7 +587,9 @@ fn test_exp() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_exp2() {
     assert_eq!(32.0, 5.0f128.exp2());
     assert_eq!(1.0, 0.0f128.exp2());
@@ -557,7 +603,9 @@ fn test_exp2() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_ln() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -573,7 +621,9 @@ fn test_ln() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_log() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -592,7 +642,9 @@ fn test_log() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_log2() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -609,7 +661,9 @@ fn test_log2() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_log10() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -659,7 +713,9 @@ fn test_to_radians() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_asinh() {
     // Lower accuracy results are allowed, use increased tolerances
     assert_eq!(0.0f128.asinh(), 0.0f128);
@@ -690,7 +746,9 @@ fn test_asinh() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_acosh() {
     assert_eq!(1.0f128.acosh(), 0.0f128);
     assert!(0.999f128.acosh().is_nan());
@@ -709,7 +767,9 @@ fn test_acosh() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_atanh() {
     assert_eq!(0.0f128.atanh(), 0.0f128);
     assert_eq!((-0.0f128).atanh(), -0.0f128);
@@ -729,7 +789,9 @@ fn test_atanh() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_gamma() {
     // precision can differ among platforms
     assert_approx_eq!(1.0f128.gamma(), 1.0f128, TOL_IMPR);
@@ -750,7 +812,9 @@ fn test_gamma() {
 }
 
 #[test]
-#[cfg(reliable_f128_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f128_math)]
 fn test_ln_gamma() {
     assert_approx_eq!(1.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
     assert_eq!(1.0f128.ln_gamma().1, 1);
@@ -781,7 +845,9 @@ fn test_real_consts() {
     assert_approx_eq!(frac_1_pi, 1f128 / pi, TOL_PRECISE);
     assert_approx_eq!(frac_2_pi, 2f128 / pi, TOL_PRECISE);
 
-    #[cfg(reliable_f128_math)]
+    #[cfg(not(miri))]
+    #[cfg(not(bootstrap))]
+    #[cfg(target_has_reliable_f128_math)]
     {
         let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI;
         let sqrt2: f128 = consts::SQRT_2;
diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs
index 0fc4df8115a..8b3b344dd46 100644
--- a/library/std/tests/floats/f16.rs
+++ b/library/std/tests/floats/f16.rs
@@ -1,5 +1,6 @@
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
-#![cfg(reliable_f16)]
+#![cfg(not(bootstrap))]
+#![cfg(target_has_reliable_f16)]
 
 use std::f16::consts;
 use std::num::FpCategory as Fp;
@@ -57,29 +58,40 @@ fn test_num_f16() {
     crate::test_num(10f16, 2f16);
 }
 
+// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
+// the intrinsics.
+
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_min_nan() {
     assert_eq!(f16::NAN.min(2.0), 2.0);
     assert_eq!(2.0f16.min(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_max_nan() {
     assert_eq!(f16::NAN.max(2.0), 2.0);
     assert_eq!(2.0f16.max(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_minimum() {
     assert!(f16::NAN.minimum(2.0).is_nan());
     assert!(2.0f16.minimum(f16::NAN).is_nan());
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_maximum() {
     assert!(f16::NAN.maximum(2.0).is_nan());
     assert!(2.0f16.maximum(f16::NAN).is_nan());
@@ -236,7 +248,9 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_floor() {
     assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
     assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
@@ -251,7 +265,9 @@ fn test_floor() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_ceil() {
     assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
     assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
@@ -266,7 +282,9 @@ fn test_ceil() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_round() {
     assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
     assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
@@ -282,7 +300,9 @@ fn test_round() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_round_ties_even() {
     assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
     assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
@@ -298,7 +318,9 @@ fn test_round_ties_even() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_trunc() {
     assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
     assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
@@ -313,7 +335,9 @@ fn test_trunc() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_fract() {
     assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
     assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
@@ -328,7 +352,9 @@ fn test_fract() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_abs() {
     assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
     assert_eq!(1f16.abs(), 1f16);
@@ -428,7 +454,9 @@ fn test_next_down() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_mul_add() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -445,7 +473,9 @@ fn test_mul_add() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_recip() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -461,7 +491,9 @@ fn test_recip() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_powi() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -476,7 +508,9 @@ fn test_powi() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_powf() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -493,7 +527,9 @@ fn test_powf() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_sqrt_domain() {
     assert!(f16::NAN.sqrt().is_nan());
     assert!(f16::NEG_INFINITY.sqrt().is_nan());
@@ -505,7 +541,9 @@ fn test_sqrt_domain() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_exp() {
     assert_eq!(1.0, 0.0f16.exp());
     assert_approx_eq!(2.718282, 1.0f16.exp(), TOL_0);
@@ -520,7 +558,9 @@ fn test_exp() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_exp2() {
     assert_eq!(32.0, 5.0f16.exp2());
     assert_eq!(1.0, 0.0f16.exp2());
@@ -534,7 +574,9 @@ fn test_exp2() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_ln() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -550,7 +592,9 @@ fn test_ln() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_log() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -569,7 +613,9 @@ fn test_log() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_log2() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -586,7 +632,9 @@ fn test_log2() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_log10() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
@@ -634,7 +682,9 @@ fn test_to_radians() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_asinh() {
     assert_eq!(0.0f16.asinh(), 0.0f16);
     assert_eq!((-0.0f16).asinh(), -0.0f16);
@@ -659,7 +709,9 @@ fn test_asinh() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_acosh() {
     assert_eq!(1.0f16.acosh(), 0.0f16);
     assert!(0.999f16.acosh().is_nan());
@@ -678,7 +730,9 @@ fn test_acosh() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_atanh() {
     assert_eq!(0.0f16.atanh(), 0.0f16);
     assert_eq!((-0.0f16).atanh(), -0.0f16);
@@ -698,7 +752,9 @@ fn test_atanh() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_gamma() {
     // precision can differ among platforms
     assert_approx_eq!(1.0f16.gamma(), 1.0f16, TOL_0);
@@ -719,7 +775,9 @@ fn test_gamma() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_ln_gamma() {
     assert_approx_eq!(1.0f16.ln_gamma().0, 0.0f16, TOL_0);
     assert_eq!(1.0f16.ln_gamma().1, 1);
@@ -752,7 +810,9 @@ fn test_real_consts() {
     assert_approx_eq!(frac_1_pi, 1f16 / pi, TOL_0);
     assert_approx_eq!(frac_2_pi, 2f16 / pi, TOL_0);
 
-    #[cfg(reliable_f16_math)]
+    #[cfg(not(miri))]
+    #[cfg(not(bootstrap))]
+    #[cfg(target_has_reliable_f16_math)]
     {
         let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI;
         let sqrt2: f16 = consts::SQRT_2;
@@ -813,7 +873,9 @@ fn test_clamp_max_is_nan() {
 }
 
 #[test]
-#[cfg(reliable_f16_math)]
+#[cfg(not(miri))]
+#[cfg(not(bootstrap))]
+#[cfg(target_has_reliable_f16_math)]
 fn test_total_cmp() {
     use core::cmp::Ordering;
 
diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs
index de5a3cdbd0f..7884fc9239e 100644
--- a/library/std/tests/floats/lib.rs
+++ b/library/std/tests/floats/lib.rs
@@ -1,4 +1,6 @@
 #![feature(f16, f128, float_algebraic, float_gamma, float_minimum_maximum)]
+#![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
+#![cfg_attr(not(bootstrap), expect(internal_features))] // for reliable_f16_f128
 
 use std::fmt;
 use std::ops::{Add, Div, Mul, Rem, Sub};
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index ed90ede7936..3c412683b94 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -421,13 +421,13 @@ impl Step for Rustc {
                 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
             }
 
+            let ra_proc_macro_srv_compiler =
+                builder.compiler_for(compiler.stage, builder.config.build, compiler.host);
+            builder.ensure(compile::Rustc::new(ra_proc_macro_srv_compiler, compiler.host));
+
             if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
                 tool::RustAnalyzerProcMacroSrv {
-                    compiler: builder.compiler_for(
-                        compiler.stage,
-                        builder.config.build,
-                        compiler.host,
-                    ),
+                    compiler: ra_proc_macro_srv_compiler,
                     target: compiler.host,
                 },
                 builder.kind,
@@ -1178,6 +1178,8 @@ impl Step for Cargo {
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         let cargo = builder.ensure(tool::Cargo { compiler, target });
         let src = builder.src.join("src/tools/cargo");
         let etc = src.join("src/etc");
@@ -1232,6 +1234,8 @@ impl Step for RustAnalyzer {
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target });
 
         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
@@ -1274,6 +1278,8 @@ impl Step for Clippy {
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         // Prepare the image directory
         // We expect clippy to build, because we've exited this step above if tool
         // state for clippy isn't testing.
@@ -1324,9 +1330,12 @@ impl Step for Miri {
         if !builder.build.unstable_features() {
             return None;
         }
+
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         let miri = builder.ensure(tool::Miri { compiler, target });
         let cargomiri = builder.ensure(tool::CargoMiri { compiler, target });
 
@@ -1463,6 +1472,8 @@ impl Step for Rustfmt {
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         let rustfmt = builder.ensure(tool::Rustfmt { compiler, target });
         let cargofmt = builder.ensure(tool::Cargofmt { compiler, target });
         let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
@@ -2328,6 +2339,8 @@ impl Step for LlvmBitcodeLinker {
         let compiler = self.compiler;
         let target = self.target;
 
+        builder.ensure(compile::Rustc::new(compiler, target));
+
         let llbc_linker =
             builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
 
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 8e2c6fc52cd..51852099dc3 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -449,6 +449,7 @@ mod dist {
     use pretty_assertions::assert_eq;
 
     use super::{Config, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, first, run_build};
+    use crate::Flags;
     use crate::core::builder::*;
 
     fn configure(host: &[&str], target: &[&str]) -> Config {
@@ -687,6 +688,37 @@ mod dist {
         );
     }
 
+    /// This also serves as an important regression test for <https://github.com/rust-lang/rust/issues/138123>
+    /// and <https://github.com/rust-lang/rust/issues/138004>.
+    #[test]
+    fn dist_all_cross() {
+        let cmd_args =
+            &["dist", "--stage", "2", "--dry-run", "--config=/does/not/exist"].map(str::to_owned);
+        let config_str = r#"
+            [rust]
+            channel = "nightly"
+
+            [build]
+            extended = true
+
+            build = "i686-unknown-haiku"
+            host = ["i686-unknown-netbsd"]
+            target = ["i686-unknown-netbsd"]
+        "#;
+        let config = Config::parse_inner(Flags::parse(cmd_args), |&_| toml::from_str(config_str));
+        let mut cache = run_build(&[], config);
+
+        // Stage 2 `compile::Rustc` should **NEVER** be cached here.
+        assert_eq!(
+            first(cache.all::<compile::Rustc>()),
+            &[
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0),
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1),
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_3, stage = 1),
+            ]
+        );
+    }
+
     #[test]
     fn build_all() {
         let build = Build::new(configure(
diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs
index 13880ad466a..5600d7b4db5 100644
--- a/src/ci/citool/src/jobs.rs
+++ b/src/ci/citool/src/jobs.rs
@@ -3,12 +3,15 @@ mod tests;
 
 use std::collections::BTreeMap;
 
+use anyhow::Context as _;
 use serde_yaml::Value;
 
 use crate::GitHubContext;
+use crate::utils::load_env_var;
 
 /// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file.
 #[derive(serde::Deserialize, Debug, Clone)]
+#[serde(deny_unknown_fields)]
 pub struct Job {
     /// Name of the job, e.g. mingw-check
     pub name: String,
@@ -26,6 +29,8 @@ pub struct Job {
     pub free_disk: Option<bool>,
     /// Documentation link to a resource that could help people debug this CI job.
     pub doc_url: Option<String>,
+    /// Whether the job is executed on AWS CodeBuild.
+    pub codebuild: Option<bool>,
 }
 
 impl Job {
@@ -80,7 +85,7 @@ impl JobDatabase {
 }
 
 pub fn load_job_db(db: &str) -> anyhow::Result<JobDatabase> {
-    let mut db: Value = serde_yaml::from_str(&db)?;
+    let mut db: Value = serde_yaml::from_str(db)?;
 
     // We need to expand merge keys (<<), because serde_yaml can't deal with them
     // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges.
@@ -107,6 +112,29 @@ struct GithubActionsJob {
     free_disk: Option<bool>,
     #[serde(skip_serializing_if = "Option::is_none")]
     doc_url: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    codebuild: Option<bool>,
+}
+
+/// Replace GitHub context variables with environment variables in job configs.
+/// Used for codebuild jobs like
+/// `codebuild-ubuntu-22-8c-$github.run_id-$github.run_attempt`
+fn substitute_github_vars(jobs: Vec<Job>) -> anyhow::Result<Vec<Job>> {
+    let run_id = load_env_var("GITHUB_RUN_ID")?;
+    let run_attempt = load_env_var("GITHUB_RUN_ATTEMPT")?;
+
+    let jobs = jobs
+        .into_iter()
+        .map(|mut job| {
+            job.os = job
+                .os
+                .replace("$github.run_id", &run_id)
+                .replace("$github.run_attempt", &run_attempt);
+            job
+        })
+        .collect();
+
+    Ok(jobs)
 }
 
 /// Skip CI jobs that are not supposed to be executed on the given `channel`.
@@ -177,6 +205,8 @@ fn calculate_jobs(
         }
         RunType::AutoJob => (db.auto_jobs.clone(), "auto", &db.envs.auto_env),
     };
+    let jobs = substitute_github_vars(jobs.clone())
+        .context("Failed to substitute GitHub context variables in jobs")?;
     let jobs = skip_jobs(jobs, channel);
     let jobs = jobs
         .into_iter()
@@ -207,6 +237,7 @@ fn calculate_jobs(
                 continue_on_error: job.continue_on_error,
                 free_disk: job.free_disk,
                 doc_url: job.doc_url,
+                codebuild: job.codebuild,
             }
         })
         .collect();
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
index 420c42bc9d8..3795859f308 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:22.04
+FROM ghcr.io/rust-lang/ubuntu:22.04
 
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 00d791eeb6b..36f7df2b069 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -288,7 +288,7 @@ args="$args --privileged"
 # `LOCAL_USER_ID` (recognized in `src/ci/run.sh`) to ensure that files are all
 # read/written as the same user as the bare-metal user.
 if [ -f /.dockerenv ]; then
-  docker create -v /checkout --name checkout alpine:3.4 /bin/true
+  docker create -v /checkout --name checkout ghcr.io/rust-lang/alpine:3.4 /bin/true
   docker cp . checkout:/checkout
   args="$args --volumes-from checkout"
 else
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 950a75721c4..88b29d2df56 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -56,6 +56,15 @@ runners:
   - &job-aarch64-linux-8c
     os: ubuntu-24.04-arm64-8core-32gb
     <<: *base-job
+
+  # Codebuild runners are provisioned in
+  # https://github.com/rust-lang/simpleinfra/blob/b7ddd5e6bec8a93ec30510cdddec02c5666fefe9/terragrunt/accounts/ci-prod/ci-runners/terragrunt.hcl#L2
+  - &job-linux-36c-codebuild
+    free_disk: true
+    codebuild: true
+    os: codebuild-ubuntu-22-36c-$github.run_id-$github.run_attempt
+    <<: *base-job
+
 envs:
   env-x86_64-apple-tests: &env-x86_64-apple-tests
     SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
@@ -151,7 +160,7 @@ auto:
     <<: *job-linux-4c
 
   - name: dist-arm-linux
-    <<: *job-linux-8c
+    <<: *job-linux-36c-codebuild
 
   - name: dist-armhf-linux
     <<: *job-linux-4c
diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh
index 055a6ac2211..ad7ee136e9c 100755
--- a/src/ci/scripts/free-disk-space.sh
+++ b/src/ci/scripts/free-disk-space.sh
@@ -14,6 +14,17 @@ isX86() {
     fi
 }
 
+# Check if we're on a GitHub hosted runner.
+# In aws codebuild, the variable RUNNER_ENVIRONMENT is "self-hosted".
+isGitHubRunner() {
+    # `:-` means "use the value of RUNNER_ENVIRONMENT if it exists, otherwise use an empty string".
+    if [[ "${RUNNER_ENVIRONMENT:-}" == "github-hosted" ]]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
 # print a line of the specified character
 printSeparationLine() {
     for ((i = 0; i < 80; i++)); do
@@ -32,7 +43,7 @@ getAvailableSpace() {
 # make Kb human readable (assume the input is Kb)
 # REF: https://unix.stackexchange.com/a/44087/60849
 formatByteCount() {
-    numfmt --to=iec-i --suffix=B --padding=7 "$1"'000'
+    numfmt --to=iec-i --suffix=B --padding=7 "${1}000"
 }
 
 # macro to output saved space
@@ -45,6 +56,11 @@ printSavedSpace() {
     after=$(getAvailableSpace)
     local saved=$((after - before))
 
+    if [ "$saved" -lt 0 ]; then
+        echo "::warning::Saved space is negative: $saved. Using '0' as saved space."
+        saved=0
+    fi
+
     echo ""
     printSeparationLine "*"
     if [ -n "${title}" ]; then
@@ -118,10 +134,14 @@ removeUnusedFilesAndDirs() {
         # Azure
         "/opt/az"
         "/usr/share/az_"*
+    )
 
+    if [ -n "${AGENT_TOOLSDIRECTORY:-}" ]; then
         # Environment variable set by GitHub Actions
-        "$AGENT_TOOLSDIRECTORY"
-    )
+        to_remove+=(
+            "${AGENT_TOOLSDIRECTORY}"
+        )
+    fi
 
     for element in "${to_remove[@]}"; do
         if [ ! -e "$element" ]; then
@@ -155,20 +175,25 @@ cleanPackages() {
         '^dotnet-.*'
         '^llvm-.*'
         '^mongodb-.*'
-        'azure-cli'
         'firefox'
         'libgl1-mesa-dri'
         'mono-devel'
         'php.*'
     )
 
-    if isX86; then
+    if isGitHubRunner; then
         packages+=(
-            'google-chrome-stable'
-            'google-cloud-cli'
-            'google-cloud-sdk'
-            'powershell'
+            azure-cli
         )
+
+        if isX86; then
+            packages+=(
+                'google-chrome-stable'
+                'google-cloud-cli'
+                'google-cloud-sdk'
+                'powershell'
+            )
+        fi
     fi
 
     sudo apt-get -qq remove -y --fix-missing "${packages[@]}"
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 872592d669d..b55ddf6e0e1 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -222,6 +222,28 @@ For more, see [the chapter on documentation tests](write-documentation/documenta
 
 See also `--test`.
 
+## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it
+
+A doctest wrapper program can be specified with the `--test-runtool` flag.
+Rustdoc will execute that wrapper instead of the doctest executable when
+running tests. The first arguments to the wrapper will be any arguments
+specified with the `--test-runtool-arg` flag, followed by the path to the
+doctest executable to run.
+
+Using these options looks like this:
+
+```bash
+$ rustdoc src/lib.rs --test-runtool path/to/runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing
+```
+
+For example, if you want to run your doctests under valgrind you might run:
+
+```bash
+$ rustdoc src/lib.rs --test-runtool valgrind
+```
+
+Another use case would be to run a test inside an emulator, or through a Virtual Machine.
+
 ## `--target`: generate documentation for the specified target triple
 
 Using this flag looks like this:
diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md
index bace2f5f953..5635f68b1b3 100644
--- a/src/doc/rustdoc/src/read-documentation/search.md
+++ b/src/doc/rustdoc/src/read-documentation/search.md
@@ -89,7 +89,7 @@ the standard library and functions that are included in the results list:
 
 ### Non-functions in type-based search
 Certain items that are not functions are treated as though they
-were a semantically equivelent function.
+were a semantically equivalent function.
 
 For example, struct fields are treated as though they were getter methods.
 This means that a search for `CpuidResult -> u32` will show
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index d4ff69a9933..69e5a5adbec 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -631,60 +631,6 @@ The generated output (formatted) will look like this:
 `--output-format html` has no effect, as the default output is HTML. This is
 accepted on stable, even though the other options for this flag aren't.
 
-## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
-
- * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores
-```
-
-This flag allows you to tag doctests with compiletest style `ignore-foo` filters that prevent
-rustdoc from running that test if the target triple string contains foo. For example:
-
-```rust
-///```ignore-foo,ignore-bar
-///assert!(2 == 2);
-///```
-struct Foo;
-```
-
-This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`.
-If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and
-the above example will be run for all targets.
-If you want to preserve backwards compatibility for older versions of rustdoc, you can use
-
-```rust
-///```ignore,ignore-foo
-///assert!(2 == 2);
-///```
-struct Foo;
-```
-
-In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will
-override `ignore`.
-
-## `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it
-
- * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
-
-Using these options looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing
-```
-
-These options can be used to run the doctest under a program, and also pass arguments to
-that program. For example, if you want to run your doctests under valgrind you might run
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
-```
-
-Another use case would be to run a test inside an emulator, or through a Virtual Machine.
-
 ## `--with-examples`: include examples of uses of items as documentation
 
  * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791)
diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md
index b921f677857..077b02d603d 100644
--- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md
+++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md
@@ -427,6 +427,43 @@ should not be merged with the others. So the previous code should use it:
 In this case, it means that the line information will not change if you add/remove other
 doctests.
 
+### Ignoring targets
+
+Attributes starting with `ignore-` can be used to ignore doctests for specific
+targets. For example, `ignore-x86_64` will avoid building doctests when the
+target name contains `x86_64`.
+
+```rust
+/// ```ignore-x86_64
+/// assert!(2 == 2);
+/// ```
+struct Foo;
+```
+
+This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`.
+
+Multiple ignore attributes can be specified to ignore multiple targets:
+
+```rust
+/// ```ignore-x86_64,ignore-windows
+/// assert!(2 == 2);
+/// ```
+struct Foo;
+```
+
+If you want to preserve backwards compatibility for older versions of rustdoc,
+you can specify both `ignore` and `ignore-`, such as:
+
+```rust
+/// ```ignore,ignore-x86_64
+/// assert!(2 == 2);
+/// ```
+struct Foo;
+```
+
+In older versions, this will be ignored on all targets, but starting with
+version CURRENT_RUSTC_VERSION, `ignore-x86_64` will override `ignore`.
+
 ### Custom CSS classes for code blocks
 
 ```rust
diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md
index 4366172fb99..8a38d155e3d 100644
--- a/src/doc/unstable-book/src/library-features/concat-idents.md
+++ b/src/doc/unstable-book/src/library-features/concat-idents.md
@@ -2,7 +2,10 @@
 
 The tracking issue for this feature is: [#29599]
 
+This feature is deprecated, to be replaced by [`macro_metavar_expr_concat`].
+
 [#29599]: https://github.com/rust-lang/rust/issues/29599
+[`macro_metavar_expr_concat`]: https://github.com/rust-lang/rust/issues/124225
 
 ------------------------
 
diff --git a/src/gcc b/src/gcc
-Subproject 13cc8243226a9028bb08ab6c5e1c5fe6d533bcd
+Subproject 0ea98a1365b81f7488073512c850e8ee951a4af
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 23a2bcd9011..4ef73ff48ed 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -124,13 +124,9 @@ pub(crate) struct Options {
     /// temporary directory if not set.
     pub(crate) persist_doctests: Option<PathBuf>,
     /// Runtool to run doctests with
-    pub(crate) runtool: Option<String>,
+    pub(crate) test_runtool: Option<String>,
     /// Arguments to pass to the runtool
-    pub(crate) runtool_args: Vec<String>,
-    /// Whether to allow ignoring doctests on a per-target basis
-    /// For example, using ignore-foo to ignore running the doctest on any target that
-    /// contains "foo" as a substring
-    pub(crate) enable_per_target_ignores: bool,
+    pub(crate) test_runtool_args: Vec<String>,
     /// Do not run doctests, compile them if should_test is active.
     pub(crate) no_run: bool,
     /// What sources are being mapped.
@@ -215,9 +211,8 @@ impl fmt::Debug for Options {
             .field("persist_doctests", &self.persist_doctests)
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
-            .field("runtool", &self.runtool)
-            .field("runtool_args", &self.runtool_args)
-            .field("enable-per-target-ignores", &self.enable_per_target_ignores)
+            .field("test_runtool", &self.test_runtool)
+            .field("test_runtool_args", &self.test_runtool_args)
             .field("run_check", &self.run_check)
             .field("no_run", &self.no_run)
             .field("test_builder_wrappers", &self.test_builder_wrappers)
@@ -779,9 +774,8 @@ impl Options {
         let unstable_opts_strs = matches.opt_strs("Z");
         let lib_strs = matches.opt_strs("L");
         let extern_strs = matches.opt_strs("extern");
-        let runtool = matches.opt_str("runtool");
-        let runtool_args = matches.opt_strs("runtool-arg");
-        let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
+        let test_runtool = matches.opt_str("test-runtool");
+        let test_runtool_args = matches.opt_strs("test-runtool-arg");
         let document_private = matches.opt_present("document-private-items");
         let document_hidden = matches.opt_present("document-hidden-items");
         let run_check = matches.opt_present("check");
@@ -843,9 +837,8 @@ impl Options {
             crate_version,
             test_run_directory,
             persist_doctests,
-            runtool,
-            runtool_args,
-            enable_per_target_ignores,
+            test_runtool,
+            test_runtool_args,
             test_builder,
             run_check,
             no_run,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 88eaa52c6de..829a9ca6e7d 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -219,11 +219,9 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
             let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
             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;
 
             let hir_collector = HirCollector::new(
                 ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()),
-                enable_per_target_ignores,
                 tcx,
             );
             let tests = hir_collector.collect_crate();
@@ -782,10 +780,10 @@ fn run_test(
     let mut cmd;
 
     let output_file = make_maybe_absolute_path(output_file);
-    if let Some(tool) = &rustdoc_options.runtool {
+    if let Some(tool) = &rustdoc_options.test_runtool {
         let tool = make_maybe_absolute_path(tool.into());
         cmd = Command::new(tool);
-        cmd.args(&rustdoc_options.runtool_args);
+        cmd.args(&rustdoc_options.test_runtool_args);
         cmd.arg(&output_file);
     } else {
         cmd = Command::new(&output_file);
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
index a0d39ce749d..497a8d7c4a7 100644
--- a/src/librustdoc/doctest/markdown.rs
+++ b/src/librustdoc/doctest/markdown.rs
@@ -104,13 +104,7 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
     };
     let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
 
-    find_testable_code(
-        &input_str,
-        &mut md_collector,
-        codes,
-        options.enable_per_target_ignores,
-        None,
-    );
+    find_testable_code(&input_str, &mut md_collector, codes, None);
 
     let mut collector = CreateRunnableDocTests::new(options.clone(), opts);
     md_collector.tests.into_iter().for_each(|t| collector.add_test(t));
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index be2dea641d7..43dcfab880b 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -63,19 +63,18 @@ impl DocTestVisitor for RustCollector {
 pub(super) struct HirCollector<'tcx> {
     codes: ErrorCodes,
     tcx: TyCtxt<'tcx>,
-    enable_per_target_ignores: bool,
     collector: RustCollector,
 }
 
 impl<'tcx> HirCollector<'tcx> {
-    pub fn new(codes: ErrorCodes, enable_per_target_ignores: bool, tcx: TyCtxt<'tcx>) -> Self {
+    pub fn new(codes: ErrorCodes, tcx: TyCtxt<'tcx>) -> Self {
         let collector = RustCollector {
             source_map: tcx.sess.psess.clone_source_map(),
             cur_path: vec![],
             position: DUMMY_SP,
             tests: vec![],
         };
-        Self { codes, enable_per_target_ignores, tcx, collector }
+        Self { codes, tcx, collector }
     }
 
     pub fn collect_crate(mut self) -> Vec<ScrapedDocTest> {
@@ -131,7 +130,6 @@ impl HirCollector<'_> {
                 &doc,
                 &mut self.collector,
                 self.codes,
-                self.enable_per_target_ignores,
                 Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)),
             );
         }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 44134bda5ea..fc46293e7ea 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -246,7 +246,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             match kind {
                 CodeBlockKind::Fenced(ref lang) => {
                     let parse_result =
-                        LangString::parse_without_check(lang, self.check_error_codes, false);
+                        LangString::parse_without_check(lang, self.check_error_codes);
                     if !parse_result.rust {
                         let added_classes = parse_result.added_classes;
                         let lang_string = if let Some(lang) = parse_result.unknown.first() {
@@ -707,17 +707,15 @@ pub(crate) fn find_testable_code<T: doctest::DocTestVisitor>(
     doc: &str,
     tests: &mut T,
     error_codes: ErrorCodes,
-    enable_per_target_ignores: bool,
     extra_info: Option<&ExtraInfo<'_>>,
 ) {
-    find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false)
+    find_codes(doc, tests, error_codes, extra_info, false)
 }
 
 pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
     doc: &str,
     tests: &mut T,
     error_codes: ErrorCodes,
-    enable_per_target_ignores: bool,
     extra_info: Option<&ExtraInfo<'_>>,
     include_non_rust: bool,
 ) {
@@ -733,12 +731,7 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
                         if lang.is_empty() {
                             Default::default()
                         } else {
-                            LangString::parse(
-                                lang,
-                                error_codes,
-                                enable_per_target_ignores,
-                                extra_info,
-                            )
+                            LangString::parse(lang, error_codes, extra_info)
                         }
                     }
                     CodeBlockKind::Indented => Default::default(),
@@ -1162,18 +1155,13 @@ impl Default for LangString {
 }
 
 impl LangString {
-    fn parse_without_check(
-        string: &str,
-        allow_error_code_check: ErrorCodes,
-        enable_per_target_ignores: bool,
-    ) -> Self {
-        Self::parse(string, allow_error_code_check, enable_per_target_ignores, None)
+    fn parse_without_check(string: &str, allow_error_code_check: ErrorCodes) -> Self {
+        Self::parse(string, allow_error_code_check, None)
     }
 
     fn parse(
         string: &str,
         allow_error_code_check: ErrorCodes,
-        enable_per_target_ignores: bool,
         extra: Option<&ExtraInfo<'_>>,
     ) -> Self {
         let allow_error_code_check = allow_error_code_check.as_bool();
@@ -1203,10 +1191,8 @@ impl LangString {
                     LangStringToken::LangToken(x)
                         if let Some(ignore) = x.strip_prefix("ignore-") =>
                     {
-                        if enable_per_target_ignores {
-                            ignores.push(ignore.to_owned());
-                            seen_rust_tags = !seen_other_tags;
-                        }
+                        ignores.push(ignore.to_owned());
+                        seen_rust_tags = !seen_other_tags;
                     }
                     LangStringToken::LangToken("rust") => {
                         data.rust = true;
@@ -1968,7 +1954,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
                     let lang_string = if syntax.is_empty() {
                         Default::default()
                     } else {
-                        LangString::parse(syntax, ErrorCodes::Yes, false, Some(extra_info))
+                        LangString::parse(syntax, ErrorCodes::Yes, Some(extra_info))
                     };
                     if !lang_string.rust {
                         continue;
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index bb42b877a2c..784d0c5d21e 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -49,7 +49,7 @@ fn test_unique_id() {
 fn test_lang_string_parse() {
     fn t(lg: LangString) {
         let s = &lg.original;
-        assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None), lg)
+        assert_eq!(LangString::parse(s, ErrorCodes::Yes, None), lg)
     }
 
     t(Default::default());
@@ -479,7 +479,7 @@ fn test_markdown_html_escape() {
 fn test_find_testable_code_line() {
     fn t(input: &str, expect: &[usize]) {
         let mut lines = Vec::<usize>::new();
-        find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
+        find_testable_code(input, &mut lines, ErrorCodes::No, None);
         assert_eq!(lines, expect);
     }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 7e17f09aecd..beaa6497b8c 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2086,6 +2086,7 @@ fn render_impl(
                     .split_summary_and_content()
                 })
                 .unwrap_or((None, None));
+
             write!(
                 w,
                 "{}",
@@ -2097,24 +2098,19 @@ fn render_impl(
                     use_absolute,
                     aliases,
                     before_dox.as_deref(),
+                    trait_.is_none() && impl_.items.is_empty(),
                 )
             )?;
             if toggled {
                 w.write_str("</summary>")?;
             }
 
-            if before_dox.is_some() {
-                if trait_.is_none() && impl_.items.is_empty() {
-                    w.write_str(
-                        "<div class=\"item-info\">\
-                         <div class=\"stab empty-impl\">This impl block contains no items.</div>\
-                     </div>",
-                    )?;
-                }
-                if let Some(after_dox) = after_dox {
-                    write!(w, "<div class=\"docblock\">{after_dox}</div>")?;
-                }
+            if before_dox.is_some()
+                && let Some(after_dox) = after_dox
+            {
+                write!(w, "<div class=\"docblock\">{after_dox}</div>")?;
             }
+
             if !default_impl_items.is_empty() || !impl_items.is_empty() {
                 w.write_str("<div class=\"impl-items\">")?;
                 close_tags.push("</div>");
@@ -2182,6 +2178,7 @@ fn render_impl_summary(
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
     doc: Option<&str>,
+    impl_is_empty: bool,
 ) -> impl fmt::Display {
     fmt::from_fn(move |w| {
         let inner_impl = i.inner_impl();
@@ -2237,6 +2234,13 @@ fn render_impl_summary(
         }
 
         if let Some(doc) = doc {
+            if impl_is_empty {
+                w.write_str(
+                    "<div class=\"item-info\">\
+                         <div class=\"stab empty-impl\">This impl block contains no items.</div>\
+                     </div>",
+                )?;
+            }
             write!(w, "<div class=\"docblock\">{doc}</div>")?;
         }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index a6dd06b76ea..19ac24a5d6e 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -2319,7 +2319,10 @@ details.toggle > summary:not(.hideme)::before {
 	doc block while aligning it with the impl block items. */
 .implementors-toggle > .docblock,
 /* We indent trait items as well. */
-#main-content > .methods > :not(.item-info) {
+#main-content > .methods > :not(.item-info),
+.impl > .item-info,
+.impl > .docblock,
+.impl + .docblock {
 	margin-left: var(--impl-items-indent);
 }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4fe5e13c3af..44bd96a7e45 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -507,28 +507,20 @@ fn opts() -> Vec<RustcOptGroup> {
             "",
         ),
         opt(
-            Unstable,
-            FlagMulti,
-            "",
-            "enable-per-target-ignores",
-            "parse ignore-foo for ignoring doctests on a per-target basis",
-            "",
-        ),
-        opt(
-            Unstable,
+            Stable,
             Opt,
             "",
-            "runtool",
+            "test-runtool",
             "",
             "The tool to run tests with when building for a different target than host",
         ),
         opt(
-            Unstable,
+            Stable,
             Multi,
             "",
-            "runtool-arg",
+            "test-runtool-arg",
             "",
-            "One (of possibly many) arguments to pass to the runtool",
+            "One argument (of possibly many) to pass to the runtool",
         ),
         opt(
             Unstable,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 761282bde7c..c9f0baaaa4c 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -212,7 +212,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> {
                 let has_docs = !i.attrs.doc_strings.is_empty();
                 let mut tests = Tests { found_tests: 0 };
 
-                find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
+                find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, None);
 
                 let has_doc_example = tests.found_tests != 0;
                 let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 70dbb944d4c..8028afea363 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -122,7 +122,7 @@ pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) {
 
     let mut tests = Tests { found_tests: 0 };
 
-    find_testable_code(dox, &mut tests, ErrorCodes::No, false, None);
+    find_testable_code(dox, &mut tests, ErrorCodes::No, None);
 
     if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples() {
         if should_have_doc_example(cx, item) {
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index e0132056d6c..b5bbe70c48c 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -414,13 +414,10 @@ pub struct Config {
     /// ABI tests.
     pub minicore_path: Utf8PathBuf,
 
-    /// If true, disable the "new" executor, and use the older libtest-based
-    /// executor to run tests instead. This is a temporary fallback, to make
-    /// manual comparative testing easier if bugs are found in the new executor.
-    ///
-    /// FIXME(Zalathar): Eventually remove this flag and remove the libtest
-    /// dependency.
-    pub no_new_executor: bool,
+    /// If true, run tests with the "new" executor that was written to replace
+    /// compiletest's dependency on libtest. Eventually this will become the
+    /// default, and the libtest dependency will be removed.
+    pub new_executor: bool,
 }
 
 impl Config {
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 0a3888a7d50..3cf13671ef0 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -202,7 +202,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "COMMAND",
         )
         .reqopt("", "minicore-path", "path to minicore aux library", "PATH")
-        .optflag("N", "no-new-executor", "disables the new test executor, and uses libtest instead")
+        .optflag("n", "new-executor", "enables the new test executor instead of using libtest")
         .optopt(
             "",
             "debugger",
@@ -448,7 +448,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
         minicore_path: opt_path(matches, "minicore-path"),
 
-        no_new_executor: matches.opt_present("no-new-executor"),
+        new_executor: matches.opt_present("new-executor"),
     }
 }
 
@@ -575,10 +575,9 @@ pub fn run_tests(config: Arc<Config>) {
     // Delegate to the executor to filter and run the big list of test structures
     // created during test discovery. When the executor decides to run a test,
     // it will return control to the rest of compiletest by calling `runtest::run`.
-    let res = if !config.no_new_executor {
+    let res = if config.new_executor {
         Ok(executor::run_tests(&config, tests))
     } else {
-        // FIXME(Zalathar): Eventually remove the libtest executor entirely.
         crate::executor::libtest::execute_tests(&config, tests)
     };
 
diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs
index 7d9f77f3752..322ef0a6c2a 100644
--- a/src/tools/miri/cargo-miri/src/main.rs
+++ b/src/tools/miri/cargo-miri/src/main.rs
@@ -53,7 +53,7 @@ fn main() {
     //     with `RustcPhase::Rustdoc`. There we perform a check-build (needed to get the expected
     //     build failures for `compile_fail` doctests) and then store a JSON file with the
     //     information needed to run this test.
-    //   - We also set `--runtool` to ourselves, which ends up in `phase_runner` with
+    //   - We also set `--test-runtool` to ourselves, which ends up in `phase_runner` with
     //     `RunnerPhase::Rustdoc`. There we parse the JSON file written in `phase_rustc` and invoke
     //     the Miri driver for interpretation.
 
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 71ea07f3463..cb62e12413c 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -666,8 +666,8 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
         if arg == "--extern" {
             // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
             forward_patched_extern_arg(&mut args, &mut cmd);
-        } else if arg == "--runtool" {
-            // An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support.
+        } else if arg == "--test-runtool" {
+            // An existing --test-runtool flag indicates cargo is running in cross-target mode, which we don't support.
             // Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag;
             // otherwise, we won't be called as rustdoc at all.
             show_error!("cross-interpreting doctests is not currently supported by Miri.");
@@ -693,8 +693,8 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
     // to let phase_cargo_rustc know to expect that. We'll use this environment variable as a flag:
     cmd.env("MIRI_CALLED_FROM_RUSTDOC", "1");
 
-    // The `--test-builder` and `--runtool` arguments are unstable rustdoc features,
-    // which are disabled by default. We first need to enable them explicitly:
+    // The `--test-builder` is an unstable rustdoc features,
+    // which is disabled by default. We first need to enable them explicitly:
     cmd.arg("-Zunstable-options");
 
     // rustdoc needs to know the right sysroot.
@@ -705,7 +705,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
     // Make rustdoc call us back.
     let cargo_miri_path = env::current_exe().expect("current executable path invalid");
     cmd.arg("--test-builder").arg(&cargo_miri_path); // invoked by forwarding most arguments
-    cmd.arg("--runtool").arg(&cargo_miri_path); // invoked with just a single path argument
+    cmd.arg("--test-runtool").arg(&cargo_miri_path); // invoked with just a single path argument
 
     debug_cmd("[cargo-miri rustdoc]", verbose, &cmd);
     exec(cmd)
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 46e045ac769..1ecaf8675c2 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-847e3ee6b0e614937eee4e6d8f61094411eadcc0
+555e1d0386f024a8359645c3217f4b3eae9be042
diff --git a/src/tools/tidy/src/gcc_submodule.rs b/src/tools/tidy/src/gcc_submodule.rs
new file mode 100644
index 00000000000..952ebe9e0cf
--- /dev/null
+++ b/src/tools/tidy/src/gcc_submodule.rs
@@ -0,0 +1,47 @@
+//! Tidy check to ensure that the commit SHA of the `src/gcc` submodule is the same as the
+//! required GCC version of the GCC codegen backend.
+
+use std::path::Path;
+use std::process::Command;
+
+pub fn check(root_path: &Path, compiler_path: &Path, bad: &mut bool) {
+    let cg_gcc_version_path = compiler_path.join("rustc_codegen_gcc/libgccjit.version");
+    let cg_gcc_version = std::fs::read_to_string(&cg_gcc_version_path)
+        .expect(&format!("Cannot read GCC version from {}", cg_gcc_version_path.display()))
+        .trim()
+        .to_string();
+
+    let git_output = Command::new("git")
+        .current_dir(root_path)
+        .arg("submodule")
+        .arg("status")
+        // --cached asks for the version that is actually committed in the repository, not the one
+        // that is currently checked out.
+        .arg("--cached")
+        .arg("src/gcc")
+        .output()
+        .expect("Cannot determine git SHA of the src/gcc checkout");
+
+    // This can return e.g.
+    // -e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc
+    //  e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be)
+    // +e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be)
+    let git_output = String::from_utf8_lossy(&git_output.stdout)
+        .trim()
+        .split_whitespace()
+        .next()
+        .unwrap_or_default()
+        .to_string();
+
+    // The SHA can start with + if the submodule is modified or - if it is not checked out.
+    let gcc_submodule_sha = git_output.trim_start_matches(&['+', '-']);
+    if gcc_submodule_sha != cg_gcc_version {
+        *bad = true;
+        eprintln!(
+            r#"Commit SHA of the src/gcc submodule (`{gcc_submodule_sha}`) does not match the required GCC version of the GCC codegen backend (`{cg_gcc_version}`).
+Make sure to set the src/gcc submodule to commit {cg_gcc_version}.
+The GCC codegen backend commit is configured at {}."#,
+            cg_gcc_version_path.display(),
+        );
+    }
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 66856f5247b..ca45f8bb84b 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -75,6 +75,7 @@ pub mod features;
 pub mod fluent_alphabetical;
 pub mod fluent_period;
 mod fluent_used;
+pub mod gcc_submodule;
 pub(crate) mod iter_header;
 pub mod known_bug;
 pub mod mir_opt_tests;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 4078d462f55..48122129b01 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -116,6 +116,7 @@ fn main() {
         check!(fluent_alphabetical, &compiler_path, bless);
         check!(fluent_period, &compiler_path);
         check!(target_policy, &root_path);
+        check!(gcc_submodule, &root_path, &compiler_path);
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
index c7be829c215..817001c514b 100644
--- a/tests/run-make/doctests-runtool/rmake.rs
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -1,4 +1,4 @@
-// Tests behavior of rustdoc `--runtool`.
+// Tests behavior of rustdoc `--test-runtool`.
 
 use std::path::PathBuf;
 
@@ -11,7 +11,7 @@ fn mkdir(name: &str) -> PathBuf {
     dir
 }
 
-// Behavior with --runtool with relative paths and --test-run-directory.
+// Behavior with --test-runtool with relative paths and --test-run-directory.
 fn main() {
     let run_dir_name = "rundir";
     let run_dir = mkdir(run_dir_name);
@@ -27,7 +27,7 @@ fn main() {
         .arg("--test")
         .arg("--test-run-directory")
         .arg(run_dir_name)
-        .arg("--runtool")
+        .arg("--test-runtool")
         .arg(&run_tool_binary)
         .extern_("t", "libt.rlib")
         .run();
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index 3f47623cb03..78ca8c863eb 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -138,12 +138,9 @@ Options:
         --show-coverage 
                         calculate percentage of public items with
                         documentation
-        --enable-per-target-ignores 
-                        parse ignore-foo for ignoring doctests on a per-target
-                        basis
-        --runtool The tool to run tests with when building for a different target than host
+        --test-runtool The tool to run tests with when building for a different target than host
                         
-        --runtool-arg One (of possibly many) arguments to pass to the runtool
+        --test-runtool-arg One argument (of possibly many) to pass to the runtool
                         
         --test-builder PATH
                         The rustc-like binary to use as the test builder
diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml
index 18e5b4d7f35..e603c3a4d22 100644
--- a/tests/rustdoc-gui/docblock-table-overflow.goml
+++ b/tests/rustdoc-gui/docblock-table-overflow.goml
@@ -11,7 +11,7 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"})
 // Checking it works on other doc blocks as well...
 
 // Logically, the ".docblock" and the "<p>" should have the same scroll width (if we exclude the margin).
-assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 816})
+assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 835})
 assert-property: ("#implementations-list > details .docblock > p", {"scrollWidth": 835})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"})
diff --git a/tests/rustdoc-gui/impl-doc-indent.goml b/tests/rustdoc-gui/impl-doc-indent.goml
new file mode 100644
index 00000000000..d647fec6d73
--- /dev/null
+++ b/tests/rustdoc-gui/impl-doc-indent.goml
@@ -0,0 +1,16 @@
+// Checks the impl block docs have the correct indent.
+go-to: "file://" + |DOC_PATH| + "/test_docs/impls_indent/struct.Context.html"
+
+// First we ensure that the impl items are indent (more on the right of the screen) than the
+// impl itself.
+store-position: ("#impl-Context", {"x": impl_x})
+store-position: ("#impl-Context > .item-info", {"x": impl_item_x})
+assert: |impl_x| < |impl_item_x|
+
+// And we ensure that all impl items have the same indent.
+assert-position: ("#impl-Context > .docblock", {"x": |impl_item_x|})
+assert-position: ("#impl-Context + .docblock", {"x": |impl_item_x|})
+
+// Same with the collapsible impl block.
+assert-position: ("#impl-Context-1 > .docblock", {"x": |impl_item_x|})
+assert-position: (".implementors-toggle > summary + .docblock", {"x": |impl_item_x|})
diff --git a/tests/rustdoc-gui/item-info-overflow.goml b/tests/rustdoc-gui/item-info-overflow.goml
index c325beb6d06..2c4e06e297c 100644
--- a/tests/rustdoc-gui/item-info-overflow.goml
+++ b/tests/rustdoc-gui/item-info-overflow.goml
@@ -21,7 +21,7 @@ compare-elements-property: (
 )
 assert-property: (
     "#impl-SimpleTrait-for-LongItemInfo2 .item-info",
-    {"scrollWidth": "916"},
+    {"scrollWidth": "935"},
 )
 // Just to be sure we're comparing the correct "item-info":
 assert-text: (
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 31f6b7f09b7..bb0015b8f9c 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -740,3 +740,29 @@ pub mod SidebarSort {
     impl Sort for Cell<u8> {}
     impl<'a> Sort for &'a str {}
 }
+
+pub mod impls_indent {
+    pub struct Context;
+
+    /// Working with objects.
+    ///
+    /// # Safety
+    ///
+    /// Functions that take indices of locals do not check bounds on these indices;
+    /// the caller must ensure that the indices are less than the number of locals
+    /// in the current stack frame.
+    impl Context {
+    }
+
+    /// Working with objects.
+    ///
+    /// # Safety
+    ///
+    /// Functions that take indices of locals do not check bounds on these indices;
+    /// the caller must ensure that the indices are less than the number of locals
+    /// in the current stack frame.
+    impl Context {
+        /// bla
+        pub fn bar() {}
+    }
+}
diff --git a/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs
new file mode 100644
index 00000000000..a21ae0664fe
--- /dev/null
+++ b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs
@@ -0,0 +1,21 @@
+// For some reason on Windows, the PATH to the libstd dylib doesn't seem to
+// carry over to running the runtool.
+//@ no-prefer-dynamic
+
+use std::path::Path;
+use std::process::Command;
+
+fn main() {
+    let args: Vec<_> = std::env::args().collect();
+    eprintln!("{args:#?}");
+    assert_eq!(args.len(), 4);
+    assert_eq!(args[1], "arg1");
+    assert_eq!(args[2], "arg2 with space");
+    let path = Path::new(&args[3]);
+    let output = Command::new(path).output().unwrap();
+    // Should fail without env var.
+    assert!(!output.status.success());
+    let output = Command::new(path).env("DOCTEST_RUNTOOL_CHECK", "xyz").output().unwrap();
+    // Should pass with env var.
+    assert!(output.status.success());
+}
diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs
new file mode 100644
index 00000000000..c4fb02e5228
--- /dev/null
+++ b/tests/rustdoc/doctest/doctest-runtool.rs
@@ -0,0 +1,13 @@
+// Tests that the --test-runtool argument works.
+
+//@ ignore-cross-compile
+//@ aux-bin: doctest-runtool.rs
+//@ compile-flags: --test
+//@ compile-flags: --test-runtool=auxiliary/bin/doctest-runtool
+//@ compile-flags: --test-runtool-arg=arg1 --test-runtool-arg
+//@ compile-flags: 'arg2 with space'
+
+/// ```
+/// assert_eq!(std::env::var("DOCTEST_RUNTOOL_CHECK"), Ok("xyz".to_string()));
+/// ```
+pub fn main() {}
diff --git a/tests/ui/asm/naked-invalid-attr.rs b/tests/ui/asm/naked-invalid-attr.rs
index c3a3131ee46..6ac9cb9e3a9 100644
--- a/tests/ui/asm/naked-invalid-attr.rs
+++ b/tests/ui/asm/naked-invalid-attr.rs
@@ -51,3 +51,12 @@ fn main() {
     #[unsafe(naked)] //~ ERROR should be applied to a function definition
     || {};
 }
+
+// Check that the path of an attribute without a name is printed correctly (issue #140082)
+#[::a]
+//~^ ERROR attribute incompatible with `#[unsafe(naked)]`
+//~| ERROR failed to resolve: use of unresolved module or unlinked crate `a`
+#[unsafe(naked)]
+extern "C" fn issue_140082() {
+    naked_asm!("")
+}
diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr
index 81d30e6475d..ef389e7d921 100644
--- a/tests/ui/asm/naked-invalid-attr.stderr
+++ b/tests/ui/asm/naked-invalid-attr.stderr
@@ -1,3 +1,9 @@
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a`
+  --> $DIR/naked-invalid-attr.rs:56:5
+   |
+LL | #[::a]
+   |     ^ use of unresolved module or unlinked crate `a`
+
 error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:13:1
    |
@@ -27,6 +33,15 @@ LL |     #[unsafe(naked)]
 LL |     || {};
    |     ----- not a function definition
 
+error[E0736]: attribute incompatible with `#[unsafe(naked)]`
+  --> $DIR/naked-invalid-attr.rs:56:1
+   |
+LL | #[::a]
+   | ^^^^^^ the `{{root}}::a` attribute is incompatible with `#[unsafe(naked)]`
+...
+LL | #[unsafe(naked)]
+   | ---------------- function marked with `#[unsafe(naked)]` here
+
 error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:22:5
    |
@@ -49,5 +64,7 @@ error: attribute should be applied to a function definition
 LL | #![unsafe(naked)]
    | ^^^^^^^^^^^^^^^^^ cannot be applied to crates
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
+Some errors have detailed explanations: E0433, E0736.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_.stderr
new file mode 100644
index 00000000000..1b6e0506001
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_reliable_f128` flag
+   |
+   = note: config `target_has_reliable_f128` is only supposed to be controlled by `--target`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_math_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_math_.stderr
new file mode 100644
index 00000000000..86e7342b8fc
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f128_math_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_reliable_f128_math` flag
+   |
+   = note: config `target_has_reliable_f128_math` is only supposed to be controlled by `--target`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_.stderr
new file mode 100644
index 00000000000..cf5000ecf27
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_reliable_f16` flag
+   |
+   = note: config `target_has_reliable_f16` is only supposed to be controlled by `--target`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_math_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_math_.stderr
new file mode 100644
index 00000000000..079e5627e4c
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.reliable_f16_math_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_reliable_f16_math` flag
+   |
+   = note: config `target_has_reliable_f16_math` is only supposed to be controlled by `--target`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
index e9661abf3ab..f7f9d2b5cd7 100644
--- a/tests/ui/cfg/disallowed-cli-cfgs.rs
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -8,6 +8,7 @@
 //@ revisions: target_thread_local_ relocation_model_
 //@ revisions: fmt_debug_
 //@ revisions: emscripten_wasm_eh_
+//@ revisions: reliable_f16_ reliable_f16_math_ reliable_f128_ reliable_f128_math_
 
 //@ [overflow_checks_]compile-flags: --cfg overflow_checks
 //@ [debug_assertions_]compile-flags: --cfg debug_assertions
@@ -35,6 +36,10 @@
 //@ [relocation_model_]compile-flags: --cfg relocation_model="a"
 //@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
 //@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
+//@ [reliable_f16_]compile-flags: --cfg target_has_reliable_f16
+//@ [reliable_f16_math_]compile-flags: --cfg target_has_reliable_f16_math
+//@ [reliable_f128_]compile-flags: --cfg target_has_reliable_f128
+//@ [reliable_f128_math_]compile-flags: --cfg target_has_reliable_f128_math
 
 fn main() {}
 
diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr
index a6f8ba65ab5..0d4c90017cf 100644
--- a/tests/ui/coercion/issue-73886.stderr
+++ b/tests/ui/coercion/issue-73886.stderr
@@ -8,9 +8,14 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/issue-73886.rs:4:13
    |
 LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+   |             ^^^^^^^^^^^^^^^^^
    |
    = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+help: consider using the `From` trait instead
+   |
+LL -     let _ = 7u32 as Option<_>;
+LL +     let _ = Option::<_>::from(7u32);
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coercion/non-primitive-cast-135412.fixed b/tests/ui/coercion/non-primitive-cast-135412.fixed
new file mode 100644
index 00000000000..5cadc9368d5
--- /dev/null
+++ b/tests/ui/coercion/non-primitive-cast-135412.fixed
@@ -0,0 +1,10 @@
+//@ run-rustfix
+
+use std::sync::Arc;
+
+fn main() {
+    let _ = Option::<_>::from(7u32);
+    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
+    let _ = Arc::<str>::from("String");
+    //~^ ERROR non-primitive cast: `&'static str` as `Arc<str>`
+}
diff --git a/tests/ui/coercion/non-primitive-cast-135412.rs b/tests/ui/coercion/non-primitive-cast-135412.rs
new file mode 100644
index 00000000000..67a3ef340d2
--- /dev/null
+++ b/tests/ui/coercion/non-primitive-cast-135412.rs
@@ -0,0 +1,10 @@
+//@ run-rustfix
+
+use std::sync::Arc;
+
+fn main() {
+    let _ = 7u32 as Option<_>;
+    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
+    let _ = "String" as Arc<str>;
+    //~^ ERROR non-primitive cast: `&'static str` as `Arc<str>`
+}
diff --git a/tests/ui/coercion/non-primitive-cast-135412.stderr b/tests/ui/coercion/non-primitive-cast-135412.stderr
new file mode 100644
index 00000000000..7e5861f83e9
--- /dev/null
+++ b/tests/ui/coercion/non-primitive-cast-135412.stderr
@@ -0,0 +1,29 @@
+error[E0605]: non-primitive cast: `u32` as `Option<_>`
+  --> $DIR/non-primitive-cast-135412.rs:6:13
+   |
+LL |     let _ = 7u32 as Option<_>;
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+help: consider using the `From` trait instead
+   |
+LL -     let _ = 7u32 as Option<_>;
+LL +     let _ = Option::<_>::from(7u32);
+   |
+
+error[E0605]: non-primitive cast: `&'static str` as `Arc<str>`
+  --> $DIR/non-primitive-cast-135412.rs:8:13
+   |
+LL |     let _ = "String" as Arc<str>;
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+help: consider using the `From` trait instead
+   |
+LL -     let _ = "String" as Arc<str>;
+LL +     let _ = Arc::<str>::from("String");
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/copy-a-resource.rs b/tests/ui/copy-a-resource.rs
deleted file mode 100644
index 55f2dd4ee6d..00000000000
--- a/tests/ui/copy-a-resource.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#[derive(Debug)]
-struct Foo {
-  i: isize,
-}
-
-impl Drop for Foo {
-    fn drop(&mut self) {}
-}
-
-fn foo(i:isize) -> Foo {
-    Foo {
-        i: i
-    }
-}
-
-fn main() {
-    let x = foo(10);
-    let _y = x.clone();
-    //~^ ERROR no method named `clone` found
-    println!("{:?}", x);
-}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index 6170250992c..8178f54b2aa 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -18,13 +18,16 @@ LL |     where
 LL |         T: AsExpression<Self::SqlType>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
 
-error[E0271]: type mismatch resolving `Integer == Text`
+error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
   --> $DIR/as_expression.rs:56:5
    |
 LL |     SelectInt.check("bar");
-   |     ^^^^^^^^^^^^^^^^^^^^^^ types differ
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
+   |
+   = help: the trait `AsExpression<Integer>` is not implemented for `&str`
+           but trait `AsExpression<Text>` is implemented for it
+   = help: for that trait implementation, expected `Text`, found `Integer`
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
index 673adb82870..86f39e43484 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
@@ -55,5 +55,5 @@ impl<T> Foo for T where T: Expression {}
 fn main() {
     SelectInt.check("bar");
     //~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
-    //[next]~| ERROR type mismatch
+    //[next]~| ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
 }
diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.rs
new file mode 100644
index 00000000000..f1b0e3b01a4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f16_math,target_has_reliable_f128,target_has_reliable_f128_math)
+
+fn main() {
+    cfg!(target_has_reliable_f16);
+    //~^ ERROR `cfg(target_has_reliable_f16)` is experimental and subject to change
+    cfg!(target_has_reliable_f16_math);
+    //~^ ERROR `cfg(target_has_reliable_f16_math)` is experimental and subject to change
+    cfg!(target_has_reliable_f128);
+    //~^ ERROR `cfg(target_has_reliable_f128)` is experimental and subject to change
+    cfg!(target_has_reliable_f128_math);
+    //~^ ERROR `cfg(target_has_reliable_f128_math)` is experimental and subject to change
+}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.stderr
new file mode 100644
index 00000000000..9b90d18699e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16-f128.stderr
@@ -0,0 +1,39 @@
+error[E0658]: `cfg(target_has_reliable_f16)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:4:10
+   |
+LL |     cfg!(target_has_reliable_f16);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `cfg(target_has_reliable_f16_math)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:6:10
+   |
+LL |     cfg!(target_has_reliable_f16_math);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `cfg(target_has_reliable_f128)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:8:10
+   |
+LL |     cfg!(target_has_reliable_f128);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `cfg(target_has_reliable_f128_math)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:10:10
+   |
+LL |     cfg!(target_has_reliable_f128_math);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.rs b/tests/ui/feature-gates/feature-gate-concat_idents.rs
index 68caf3d71e9..4fc3b691597 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents.rs
+++ b/tests/ui/feature-gates/feature-gate-concat_idents.rs
@@ -1,3 +1,5 @@
+#![expect(deprecated)] // concat_idents is deprecated
+
 const XY_1: i32 = 10;
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.stderr b/tests/ui/feature-gates/feature-gate-concat_idents.stderr
index d0f4fe62d04..6399424eecd 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-concat_idents.rs:5:13
+  --> $DIR/feature-gate-concat_idents.rs:7:13
    |
 LL |     let a = concat_idents!(X, Y_1);
    |             ^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     let a = concat_idents!(X, Y_1);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-concat_idents.rs:6:13
+  --> $DIR/feature-gate-concat_idents.rs:8:13
    |
 LL |     let b = concat_idents!(X, Y_2);
    |             ^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.rs b/tests/ui/feature-gates/feature-gate-concat_idents2.rs
index 9660ffeafa5..bc2b4f7cddf 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents2.rs
+++ b/tests/ui/feature-gates/feature-gate-concat_idents2.rs
@@ -1,3 +1,5 @@
+#![expect(deprecated)] // concat_idents is deprecated
+
 fn main() {
     concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
                           //~| ERROR cannot find value `ab` in this scope
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
index b42a1d999e4..a770c1a348b 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-concat_idents2.rs:2:5
+  --> $DIR/feature-gate-concat_idents2.rs:4:5
    |
 LL |     concat_idents!(a, b);
    |     ^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     concat_idents!(a, b);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0425]: cannot find value `ab` in this scope
-  --> $DIR/feature-gate-concat_idents2.rs:2:5
+  --> $DIR/feature-gate-concat_idents2.rs:4:5
    |
 LL |     concat_idents!(a, b);
    |     ^^^^^^^^^^^^^^^^^^^^ not found in this scope
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.rs b/tests/ui/feature-gates/feature-gate-concat_idents3.rs
index 81710fd9fb0..d4a0d2e6bb0 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents3.rs
+++ b/tests/ui/feature-gates/feature-gate-concat_idents3.rs
@@ -1,3 +1,5 @@
+#![expect(deprecated)] // concat_idents is deprecated
+
 const XY_1: i32 = 10;
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
index b186601d0ed..7d929322bc0 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-concat_idents3.rs:5:20
+  --> $DIR/feature-gate-concat_idents3.rs:7:20
    |
 LL |     assert_eq!(10, concat_idents!(X, Y_1));
    |                    ^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     assert_eq!(10, concat_idents!(X, Y_1));
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-concat_idents3.rs:6:20
+  --> $DIR/feature-gate-concat_idents3.rs:8:20
    |
 LL |     assert_eq!(20, concat_idents!(X, Y_2));
    |                    ^^^^^^^^^^^^^
diff --git a/tests/ui/float/target-has-reliable-nightly-float.rs b/tests/ui/float/target-has-reliable-nightly-float.rs
new file mode 100644
index 00000000000..ad8600fc635
--- /dev/null
+++ b/tests/ui/float/target-has-reliable-nightly-float.rs
@@ -0,0 +1,31 @@
+//@ run-pass
+//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f16_math,target_has_reliable_f128,target_has_reliable_f128_math)
+// Verify that the feature gates and config work and are registered as known config
+// options.
+
+#![deny(unexpected_cfgs)]
+#![feature(cfg_target_has_reliable_f16_f128)]
+
+#[cfg(target_has_reliable_f16)]
+pub fn has_f16() {}
+
+#[cfg(target_has_reliable_f16_math)]
+pub fn has_f16_math() {}
+
+#[cfg(target_has_reliable_f128 )]
+pub fn has_f128() {}
+
+#[cfg(target_has_reliable_f128_math)]
+pub fn has_f128_math() {}
+
+fn main() {
+    if cfg!(target_arch = "aarch64") && cfg!(target_os = "linux") {
+        // Aarch64+Linux is one target that has support for all features, so use it to spot
+        // check that the compiler does indeed enable these gates.
+
+        assert!(cfg!(target_has_reliable_f16));
+        assert!(cfg!(target_has_reliable_f16_math));
+        assert!(cfg!(target_has_reliable_f128));
+        assert!(cfg!(target_has_reliable_f128_math));
+    }
+}
diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.rs b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.rs
new file mode 100644
index 00000000000..1ee3bfd1233
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.rs
@@ -0,0 +1,23 @@
+trait ServerFn {
+    type Output;
+    fn run_body() -> impl Sized;
+}
+struct MyServerFn {}
+
+macro_rules! f {
+    () => {
+        impl ServerFn for MyServerFn {
+            type Output = ();
+            fn run_body() -> impl Sized {}
+        }
+    };
+}
+
+f! {}
+
+fn problem<T: ServerFn<Output = i64>>(_: T) {}
+
+fn main() {
+    problem(MyServerFn {});
+    //~^ ERROR type mismatch resolving `<MyServerFn as ServerFn>::Output == i64`
+}
diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr
new file mode 100644
index 00000000000..b4c022d3521
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr
@@ -0,0 +1,26 @@
+error[E0271]: type mismatch resolving `<MyServerFn as ServerFn>::Output == i64`
+  --> $DIR/dont-probe-missing-item-name-4.rs:21:13
+   |
+LL |     problem(MyServerFn {});
+   |     ------- ^^^^^^^^^^^^^ type mismatch resolving `<MyServerFn as ServerFn>::Output == i64`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: expected this to be `i64`
+  --> $DIR/dont-probe-missing-item-name-4.rs:10:27
+   |
+LL |             type Output = ();
+   |                           ^^
+...
+LL | f! {}
+   | ----- in this macro invocation
+note: required by a bound in `problem`
+  --> $DIR/dont-probe-missing-item-name-4.rs:18:24
+   |
+LL | fn problem<T: ServerFn<Output = i64>>(_: T) {}
+   |                        ^^^^^^^^^^^^ required by this bound in `problem`
+   = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/issues/issue-32950.rs b/tests/ui/issues/issue-32950.rs
index 27d68a11c1f..b51ac296776 100644
--- a/tests/ui/issues/issue-32950.rs
+++ b/tests/ui/issues/issue-32950.rs
@@ -1,4 +1,5 @@
 #![feature(concat_idents)]
+#![expect(deprecated)] // concat_idents is deprecated
 
 #[derive(Debug)]
 struct Baz<T>(
diff --git a/tests/ui/issues/issue-32950.stderr b/tests/ui/issues/issue-32950.stderr
index 3cdf35af1d8..38a82542f89 100644
--- a/tests/ui/issues/issue-32950.stderr
+++ b/tests/ui/issues/issue-32950.stderr
@@ -1,11 +1,11 @@
 error: `derive` cannot be used on items with type macros
-  --> $DIR/issue-32950.rs:5:5
+  --> $DIR/issue-32950.rs:6:5
    |
 LL |     concat_idents!(Foo, Bar)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0412]: cannot find type `FooBar` in this scope
-  --> $DIR/issue-32950.rs:5:5
+  --> $DIR/issue-32950.rs:6:5
    |
 LL |     concat_idents!(Foo, Bar)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
diff --git a/tests/ui/issues/issue-50403.rs b/tests/ui/issues/issue-50403.rs
index ab22aff26d9..f14958afc34 100644
--- a/tests/ui/issues/issue-50403.rs
+++ b/tests/ui/issues/issue-50403.rs
@@ -1,4 +1,5 @@
 #![feature(concat_idents)]
+#![expect(deprecated)] // concat_idents is deprecated
 
 fn main() {
     let x = concat_idents!(); //~ ERROR `concat_idents!()` takes 1 or more arguments
diff --git a/tests/ui/issues/issue-50403.stderr b/tests/ui/issues/issue-50403.stderr
index 193d815d519..e7dd05bb018 100644
--- a/tests/ui/issues/issue-50403.stderr
+++ b/tests/ui/issues/issue-50403.stderr
@@ -1,5 +1,5 @@
 error: `concat_idents!()` takes 1 or more arguments
-  --> $DIR/issue-50403.rs:4:13
+  --> $DIR/issue-50403.rs:5:13
    |
 LL |     let x = concat_idents!();
    |             ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs
index 79beffbe986..091d64ea5d9 100644
--- a/tests/ui/macros/macros-nonfatal-errors.rs
+++ b/tests/ui/macros/macros-nonfatal-errors.rs
@@ -5,6 +5,7 @@
 
 #![feature(trace_macros, concat_idents)]
 #![feature(stmt_expr_attributes)]
+#![expect(deprecated)] // concat_idents is deprecated
 
 use std::arch::asm;
 
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index 44194b506a4..2f990cb24e2 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -1,5 +1,5 @@
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:13:5
+  --> $DIR/macros-nonfatal-errors.rs:14:5
    |
 LL |     #[default]
    |     ^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     #[default]
    = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:18:36
+  --> $DIR/macros-nonfatal-errors.rs:19:36
    |
 LL | struct DefaultInnerAttrTupleStruct(#[default] ());
    |                                    ^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | struct DefaultInnerAttrTupleStruct(#[default] ());
    = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:22:1
+  --> $DIR/macros-nonfatal-errors.rs:23:1
    |
 LL | #[default]
    | ^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | #[default]
    = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:26:1
+  --> $DIR/macros-nonfatal-errors.rs:27:1
    |
 LL | #[default]
    | ^^^^^^^^^^
@@ -31,7 +31,7 @@ LL | #[default]
    = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:36:11
+  --> $DIR/macros-nonfatal-errors.rs:37:11
    |
 LL |     Foo = #[default] 0,
    |           ^^^^^^^^^^
@@ -39,7 +39,7 @@ LL |     Foo = #[default] 0,
    = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:37:14
+  --> $DIR/macros-nonfatal-errors.rs:38:14
    |
 LL |     Bar([u8; #[default] 1]),
    |              ^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     Bar([u8; #[default] 1]),
    = help: consider a manual implementation of `Default`
 
 error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
-  --> $DIR/macros-nonfatal-errors.rs:42:10
+  --> $DIR/macros-nonfatal-errors.rs:43:10
    |
 LL |   #[derive(Default)]
    |            ^^^^^^^
@@ -67,7 +67,7 @@ LL |     #[default] Bar,
    |     ++++++++++
 
 error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
-  --> $DIR/macros-nonfatal-errors.rs:48:10
+  --> $DIR/macros-nonfatal-errors.rs:49:10
    |
 LL |   #[derive(Default)]
    |            ^^^^^^^
@@ -78,7 +78,7 @@ LL | | }
    | |_- this enum needs a unit variant marked with `#[default]`
 
 error: multiple declared defaults
-  --> $DIR/macros-nonfatal-errors.rs:54:10
+  --> $DIR/macros-nonfatal-errors.rs:55:10
    |
 LL | #[derive(Default)]
    |          ^^^^^^^
@@ -95,7 +95,7 @@ LL |     Baz,
    = note: only one variant can be default
 
 error: `#[default]` attribute does not accept a value
-  --> $DIR/macros-nonfatal-errors.rs:66:5
+  --> $DIR/macros-nonfatal-errors.rs:67:5
    |
 LL |     #[default = 1]
    |     ^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL |     #[default = 1]
    = help: try using `#[default]`
 
 error: multiple `#[default]` attributes
-  --> $DIR/macros-nonfatal-errors.rs:74:5
+  --> $DIR/macros-nonfatal-errors.rs:75:5
    |
 LL |     #[default]
    |     ---------- `#[default]` used here
@@ -114,13 +114,13 @@ LL |     Foo,
    |
    = note: only one `#[default]` attribute is needed
 help: try removing this
-  --> $DIR/macros-nonfatal-errors.rs:73:5
+  --> $DIR/macros-nonfatal-errors.rs:74:5
    |
 LL |     #[default]
    |     ^^^^^^^^^^
 
 error: multiple `#[default]` attributes
-  --> $DIR/macros-nonfatal-errors.rs:84:5
+  --> $DIR/macros-nonfatal-errors.rs:85:5
    |
 LL |     #[default]
    |     ---------- `#[default]` used here
@@ -132,7 +132,7 @@ LL |     Foo,
    |
    = note: only one `#[default]` attribute is needed
 help: try removing these
-  --> $DIR/macros-nonfatal-errors.rs:81:5
+  --> $DIR/macros-nonfatal-errors.rs:82:5
    |
 LL |     #[default]
    |     ^^^^^^^^^^
@@ -142,7 +142,7 @@ LL |     #[default]
    |     ^^^^^^^^^^
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:91:5
+  --> $DIR/macros-nonfatal-errors.rs:92:5
    |
 LL |     Foo {},
    |     ^^^
@@ -150,7 +150,7 @@ LL |     Foo {},
    = help: consider a manual implementation of `Default`
 
 error: default variant must be exhaustive
-  --> $DIR/macros-nonfatal-errors.rs:99:5
+  --> $DIR/macros-nonfatal-errors.rs:100:5
    |
 LL |     #[non_exhaustive]
    |     ----------------- declared `#[non_exhaustive]` here
@@ -160,37 +160,37 @@ LL |     Foo,
    = help: consider a manual implementation of `Default`
 
 error: asm template must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:104:10
+  --> $DIR/macros-nonfatal-errors.rs:105:10
    |
 LL |     asm!(invalid);
    |          ^^^^^^^
 
 error: `concat_idents!()` requires ident args
-  --> $DIR/macros-nonfatal-errors.rs:107:5
+  --> $DIR/macros-nonfatal-errors.rs:108:5
    |
 LL |     concat_idents!("not", "idents");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:109:17
+  --> $DIR/macros-nonfatal-errors.rs:110:17
    |
 LL |     option_env!(invalid);
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:110:10
+  --> $DIR/macros-nonfatal-errors.rs:111:10
    |
 LL |     env!(invalid);
    |          ^^^^^^^
 
 error: `env!()` takes 1 or 2 arguments
-  --> $DIR/macros-nonfatal-errors.rs:111:5
+  --> $DIR/macros-nonfatal-errors.rs:112:5
    |
 LL |     env!(foo, abr, baz);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
-  --> $DIR/macros-nonfatal-errors.rs:112:5
+  --> $DIR/macros-nonfatal-errors.rs:113:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -198,7 +198,7 @@ LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    = help: use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
 
 error: format argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:114:13
+  --> $DIR/macros-nonfatal-errors.rs:115:13
    |
 LL |     format!(invalid);
    |             ^^^^^^^
@@ -209,43 +209,43 @@ LL |     format!("{}", invalid);
    |             +++++
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:116:14
+  --> $DIR/macros-nonfatal-errors.rs:117:14
    |
 LL |     include!(invalid);
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:118:18
+  --> $DIR/macros-nonfatal-errors.rs:119:18
    |
 LL |     include_str!(invalid);
    |                  ^^^^^^^
 
 error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
-  --> $DIR/macros-nonfatal-errors.rs:119:5
+  --> $DIR/macros-nonfatal-errors.rs:120:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:120:20
+  --> $DIR/macros-nonfatal-errors.rs:121:20
    |
 LL |     include_bytes!(invalid);
    |                    ^^^^^^^
 
 error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
-  --> $DIR/macros-nonfatal-errors.rs:121:5
+  --> $DIR/macros-nonfatal-errors.rs:122:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trace_macros! accepts only `true` or `false`
-  --> $DIR/macros-nonfatal-errors.rs:123:5
+  --> $DIR/macros-nonfatal-errors.rs:124:5
    |
 LL |     trace_macros!(invalid);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: default variant must be exhaustive
-  --> $DIR/macros-nonfatal-errors.rs:133:9
+  --> $DIR/macros-nonfatal-errors.rs:134:9
    |
 LL |         #[non_exhaustive]
    |         ----------------- declared `#[non_exhaustive]` here
@@ -255,7 +255,7 @@ LL |         Foo,
    = help: consider a manual implementation of `Default`
 
 error: cannot find macro `llvm_asm` in this scope
-  --> $DIR/macros-nonfatal-errors.rs:105:5
+  --> $DIR/macros-nonfatal-errors.rs:106:5
    |
 LL |     llvm_asm!(invalid);
    |     ^^^^^^^^
diff --git a/tests/ui/fail-simple.rs b/tests/ui/macros/no-matching-rule.rs
index 55e547ee72b..55e547ee72b 100644
--- a/tests/ui/fail-simple.rs
+++ b/tests/ui/macros/no-matching-rule.rs
diff --git a/tests/ui/fail-simple.stderr b/tests/ui/macros/no-matching-rule.stderr
index 50c350b3ef5..a6312a843f3 100644
--- a/tests/ui/fail-simple.stderr
+++ b/tests/ui/macros/no-matching-rule.stderr
@@ -1,5 +1,5 @@
 error: no rules expected `@`
-  --> $DIR/fail-simple.rs:2:12
+  --> $DIR/no-matching-rule.rs:2:12
    |
 LL |     panic!(@);
    |            ^ no rules expected this token in macro call
diff --git a/tests/ui/methods/clone-missing.rs b/tests/ui/methods/clone-missing.rs
new file mode 100644
index 00000000000..f2e4ad268c6
--- /dev/null
+++ b/tests/ui/methods/clone-missing.rs
@@ -0,0 +1,19 @@
+// This test checks that calling `.clone()` on a type that does not implement the `Clone` trait
+// results in a compilation error. The `Foo` struct does not derive or implement `Clone`,
+// so attempting to clone it should fail.
+
+struct Foo {
+  i: isize,
+}
+
+fn foo(i:isize) -> Foo {
+    Foo {
+        i: i
+    }
+}
+
+fn main() {
+    let x = foo(10);
+    let _y = x.clone();
+    //~^ ERROR no method named `clone` found
+}
diff --git a/tests/ui/copy-a-resource.stderr b/tests/ui/methods/clone-missing.stderr
index ff1e28bf961..4ab1aae4934 100644
--- a/tests/ui/copy-a-resource.stderr
+++ b/tests/ui/methods/clone-missing.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `clone` found for struct `Foo` in the current scope
-  --> $DIR/copy-a-resource.rs:18:16
+  --> $DIR/clone-missing.rs:17:16
    |
 LL | struct Foo {
    | ---------- method `clone` not found for this struct
diff --git a/tests/ui/modules/mod-pub-access.rs b/tests/ui/modules/mod-pub-access.rs
new file mode 100644
index 00000000000..c07e7a2ff30
--- /dev/null
+++ b/tests/ui/modules/mod-pub-access.rs
@@ -0,0 +1,11 @@
+//@ run-pass
+// This is a name resolution smoke test that ensures paths with more than one
+// segment (e.g., `foo::bar`) resolve correctly.
+// It also serves as a basic visibility test — confirming that a `pub` item
+// inside a private module can still be accessed from outside that module.
+
+mod foo {
+    pub fn bar(_offset: usize) {}
+}
+
+fn main() { foo::bar(0); }
diff --git a/tests/ui/path.rs b/tests/ui/path.rs
deleted file mode 100644
index bd7b99ac01a..00000000000
--- a/tests/ui/path.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ run-pass
-
-mod foo {
-    pub fn bar(_offset: usize) { }
-}
-
-pub fn main() { foo::bar(0); }
diff --git a/tests/ui/capture1.rs b/tests/ui/resolve/fn-item-cant-capture-dynamic-env.rs
index 4f8c04e3fa9..4f8c04e3fa9 100644
--- a/tests/ui/capture1.rs
+++ b/tests/ui/resolve/fn-item-cant-capture-dynamic-env.rs
diff --git a/tests/ui/capture1.stderr b/tests/ui/resolve/fn-item-cant-capture-dynamic-env.stderr
index 8027430de52..6b3e8792011 100644
--- a/tests/ui/capture1.stderr
+++ b/tests/ui/resolve/fn-item-cant-capture-dynamic-env.stderr
@@ -1,5 +1,5 @@
 error[E0434]: can't capture dynamic environment in a fn item
-  --> $DIR/capture1.rs:3:32
+  --> $DIR/fn-item-cant-capture-dynamic-env.rs:3:32
    |
 LL |     fn foo() -> isize { return bar; }
    |                                ^^^
diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs
index 2ee164cdfd8..50a05eecb03 100644
--- a/tests/ui/simd/intrinsic/generic-comparison-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(repr_simd, core_intrinsics, concat_idents)]
+#![feature(repr_simd, core_intrinsics, macro_metavar_expr_concat)]
 #![allow(non_camel_case_types)]
 
 use std::intrinsics::simd::{simd_eq, simd_ge, simd_gt, simd_le, simd_lt, simd_ne};
@@ -19,7 +19,7 @@ macro_rules! cmp {
     ($method: ident($lhs: expr, $rhs: expr)) => {{
         let lhs = $lhs;
         let rhs = $rhs;
-        let e: u32x4 = concat_idents!(simd_, $method)($lhs, $rhs);
+        let e: u32x4 = ${concat(simd_, $method)}($lhs, $rhs);
         // assume the scalar version is correct/the behaviour we want.
         assert!((e.0[0] != 0) == lhs.0[0].$method(&rhs.0[0]));
         assert!((e.0[1] != 0) == lhs.0[1].$method(&rhs.0[1]));
diff --git a/tests/ui/syntax-extension-minor.rs b/tests/ui/syntax-extension-minor.rs
index cdd572b50fc..826990a89a5 100644
--- a/tests/ui/syntax-extension-minor.rs
+++ b/tests/ui/syntax-extension-minor.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 
 #![feature(concat_idents)]
+#![expect(deprecated)] // concat_idents is deprecated
 
 pub fn main() {
     struct Foo;
diff --git a/tests/ui/traits/next-solver/normalize/eager-norm-pre-normalizes-to.rs b/tests/ui/traits/next-solver/normalize/eager-norm-pre-normalizes-to.rs
new file mode 100644
index 00000000000..ea18ac54c05
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize/eager-norm-pre-normalizes-to.rs
@@ -0,0 +1,44 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+// A regression test for trait-system-refactor-initiative#184.
+//
+// When adding nested goals we replace aliases with infer vars
+// and add `AliasRelate` goals to constrain them. When doing this
+// for `NormalizesTo` goals, we then first tries to prove the
+// `NormalizesTo` goal and then normalized the nested aliases.
+
+trait Trait<T> {
+    type Assoc;
+}
+impl<T, U> Trait<U> for T {
+    type Assoc = ();
+}
+
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+trait Relate<T> {
+    type Alias;
+}
+impl<T, U> Relate<U> for T {
+    type Alias = <T as Trait<<U as Id>::This>>::Assoc;
+}
+
+
+fn guide_me<T: Trait<u32>>() {
+    // Normalizing `<T as Relate<i32>>::Alias` relates the associated type with an unconstrained
+    // term. This resulted in a `NormalizesTo(<T as Trait<<U as Id>::This>>::Assoc, ?x)` goal.
+    // We replace `<i32 as Id>::This` with an infer var `?y`, resulting in the following goals:
+    // - `NormalizesTo(<T as Trait<?y>::Assoc, ?x)`
+    // - `AliasRelate(<i32 as Id>::This, ?y)`
+    //
+    // When proving the `NormalizesTo` goal first, we incompletely constrain `?y` to `u32`,
+    // causing an unexpected type mismatch.
+    let _: <T as Relate<i32>>::Alias;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs
index 5284220ac38..3150d9a88d0 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs
+++ b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+//@ compile-flags: -Znext-solver
 
 // When canonicalizing a response in the trait solver, we bail with overflow
 // if there are too many non-region inference variables. Doing so in normalizes-to
diff --git a/tests/ui/transmute/auxiliary/unnecessary-transmute-path-remap-ice-140277-trans.rs b/tests/ui/transmute/auxiliary/unnecessary-transmute-path-remap-ice-140277-trans.rs
new file mode 100644
index 00000000000..0f273a6f536
--- /dev/null
+++ b/tests/ui/transmute/auxiliary/unnecessary-transmute-path-remap-ice-140277-trans.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: --remap-path-prefix=/=/non-existent
+// helper for ../unnecessary-transmute-path-remap-ice-140277.rs
+
+#[macro_export]
+macro_rules! transmute {
+    ($e:expr) => {{
+        let e = $e;
+        std::mem::transmute(e)
+    }};
+}
diff --git a/tests/ui/transmute/unnecessary-transmute-path-remap-ice-140277.rs b/tests/ui/transmute/unnecessary-transmute-path-remap-ice-140277.rs
new file mode 100644
index 00000000000..756ce7b3d50
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmute-path-remap-ice-140277.rs
@@ -0,0 +1,10 @@
+//@ aux-crate: zerocopy=unnecessary-transmute-path-remap-ice-140277-trans.rs
+//@ check-pass
+// tests for a regression in linting for unnecessary transmutes
+// where a span was inacessible for snippet procuring,
+// when remap-path-prefix was set, causing a panic.
+
+fn bytes_at_home(x: [u8; 4]) -> u32 {
+    unsafe { zerocopy::transmute!(x) }
+}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index 4391bf01dc9..7a540d2a574 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -22,7 +22,7 @@ impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     #[define_opaque(Bar)]
     fn convert(_i: In) -> Self::Out {
-        //[next]~^  ERROR: cannot satisfy `Bar == _`
+        //[next]~^  ERROR: type annotations needed: cannot satisfy `Bar == _`
         //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`
         unreachable!();
     }
diff --git a/tests/ui/type-alias/type-param.rs b/tests/ui/type-alias/type-param.rs
new file mode 100644
index 00000000000..f8e73518bad
--- /dev/null
+++ b/tests/ui/type-alias/type-param.rs
@@ -0,0 +1,11 @@
+//@ run-pass
+// This is a smoke test to ensure that type aliases with type parameters
+// are accepted by the compiler and that the parameters are correctly
+// resolved in the aliased item type.
+
+#![allow(dead_code)]
+
+type Foo<T> = extern "C" fn(T) -> bool;
+type Bar<T> = fn(T) -> bool;
+
+fn main() {}
diff --git a/tests/ui/type-param.rs b/tests/ui/type-param.rs
deleted file mode 100644
index e7cf0e5446b..00000000000
--- a/tests/ui/type-param.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-pass
-
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-
-
-
-type lteq<T> = extern "C" fn(T) -> bool;
-
-pub fn main() { }
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 0fb5a26c5aa..5697f615b97 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -839,6 +839,7 @@ mod types {
     }
 
     /// TyKind::MacCall
+    #[expect(deprecated)] // concat_idents is deprecated
     fn ty_mac_call() {
         let _: concat_idents!(T);
         let _: concat_idents![T];
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 8febd2d6d49..841edf63c91 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -359,6 +359,7 @@ mod expressions {
 
 
 
+        // concat_idents is deprecated
 
 
 
@@ -674,6 +675,7 @@ mod types {
         /*! there is no syntax for this */
     }
     /// TyKind::MacCall
+    #[expect(deprecated)]
     fn ty_mac_call() { let _: T; let _: T; let _: T; }
     /// TyKind::CVarArgs
     fn ty_c_var_args() {