about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/alloc/src/vec/into_iter.rs2
-rw-r--r--library/alloc/src/vec/splice.rs2
-rw-r--r--library/core/src/future/async_drop.rs311
-rw-r--r--library/core/src/future/mod.rs3
-rw-r--r--library/core/src/intrinsics/mod.rs2
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/ops/drop.rs7
-rw-r--r--library/core/src/ops/mod.rs1
-rw-r--r--library/core/src/panicking.rs94
-rw-r--r--library/core/src/ptr/const_ptr.rs6
-rw-r--r--library/core/src/ptr/mut_ptr.rs9
-rw-r--r--library/core/src/ptr/non_null.rs8
-rw-r--r--library/core/src/slice/iter.rs1
-rw-r--r--library/core/src/slice/mod.rs127
-rw-r--r--library/std/Cargo.toml6
-rw-r--r--library/std/build.rs110
-rw-r--r--library/std/src/f128.rs270
-rw-r--r--library/std/src/f16.rs270
-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
21 files changed, 861 insertions, 623 deletions
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 3eee988b6c9..1af110691ba 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -168,7 +168,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
 
         // SAFETY: This allocation originally came from a `Vec`, so it passes
         // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
-        // so the `sub_ptr`s below cannot wrap, and will produce a well-formed
+        // so the `offset_from_unsigned`s below cannot wrap, and will produce a well-formed
         // range. `end` ≤ `buf + cap`, so the range will be in-bounds.
         // Taking `alloc` is ok because nothing else is going to look at it,
         // since our `Drop` impl isn't going to run so there's no more code.
diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs
index ca5cb17f8bf..ed1a0dda76d 100644
--- a/library/alloc/src/vec/splice.rs
+++ b/library/alloc/src/vec/splice.rs
@@ -59,7 +59,7 @@ impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {
         // and moving things into the final place.
         // Which means we can replace the slice::Iter with pointers that won't point to deallocated
         // memory, so that Drain::drop is still allowed to call iter.len(), otherwise it would break
-        // the ptr.sub_ptr contract.
+        // the ptr.offset_from_unsigned contract.
         self.drain.iter = (&[]).iter();
 
         unsafe {
diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs
index f1778a4d782..fc4f95a98b4 100644
--- a/library/core/src/future/async_drop.rs
+++ b/library/core/src/future/async_drop.rs
@@ -1,284 +1,51 @@
 #![unstable(feature = "async_drop", issue = "126482")]
 
-use crate::fmt;
-use crate::future::{Future, IntoFuture};
-use crate::intrinsics::discriminant_value;
-use crate::marker::{DiscriminantKind, PhantomPinned};
-use crate::mem::MaybeUninit;
-use crate::pin::Pin;
-use crate::task::{Context, Poll, ready};
-
-/// Asynchronously drops a value by running `AsyncDrop::async_drop`
-/// on a value and its fields recursively.
-#[unstable(feature = "async_drop", issue = "126482")]
-pub fn async_drop<T>(value: T) -> AsyncDropOwning<T> {
-    AsyncDropOwning { value: MaybeUninit::new(value), dtor: None, _pinned: PhantomPinned }
-}
-
-/// A future returned by the [`async_drop`].
-#[unstable(feature = "async_drop", issue = "126482")]
-pub struct AsyncDropOwning<T> {
-    value: MaybeUninit<T>,
-    dtor: Option<AsyncDropInPlace<T>>,
-    _pinned: PhantomPinned,
-}
-
-#[unstable(feature = "async_drop", issue = "126482")]
-impl<T> fmt::Debug for AsyncDropOwning<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("AsyncDropOwning").finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "async_drop", issue = "126482")]
-impl<T> Future for AsyncDropOwning<T> {
-    type Output = ();
-
-    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
-        // SAFETY: Self is pinned thus it is ok to store references to self
-        unsafe {
-            let this = self.get_unchecked_mut();
-            let dtor = Pin::new_unchecked(
-                this.dtor.get_or_insert_with(|| async_drop_in_place(this.value.as_mut_ptr())),
-            );
-            // AsyncDestuctors are idempotent so Self gets idempotency as well
-            dtor.poll(cx)
-        }
-    }
-}
+#[allow(unused_imports)]
+use core::future::Future;
 
-#[lang = "async_drop_in_place"]
-#[allow(unconditional_recursion)]
-// FIXME: Consider if `#[rustc_diagnostic_item = "ptr_drop_in_place"]` is needed?
-unsafe fn async_drop_in_place_raw<T: ?Sized>(
-    to_drop: *mut T,
-) -> <T as AsyncDestruct>::AsyncDestructor {
-    // Code here does not matter - this is replaced by the
-    // real async drop glue constructor by the compiler.
-
-    // SAFETY: see comment above
-    unsafe { async_drop_in_place_raw(to_drop) }
-}
+#[allow(unused_imports)]
+use crate::pin::Pin;
+#[allow(unused_imports)]
+use crate::task::{Context, Poll};
 
-/// Creates the asynchronous destructor of the pointed-to value.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `to_drop` must be [valid](crate::ptr#safety) for both reads and writes.
-///
-/// * `to_drop` must be properly aligned, even if `T` has size 0.
+/// Async version of Drop trait.
 ///
-/// * `to_drop` must be nonnull, even if `T` has size 0.
+/// When a value is no longer needed, Rust will run a "destructor" on that value.
+/// The most common way that a value is no longer needed is when it goes out of
+/// scope. Destructors may still run in other circumstances, but we're going to
+/// focus on scope for the examples here. To learn about some of those other cases,
+/// please see [the reference] section on destructors.
 ///
-/// * The value `to_drop` points to must be valid for async dropping,
-///   which may mean it must uphold additional invariants. These
-///   invariants depend on the type of the value being dropped. For
-///   instance, when dropping a Box, the box's pointer to the heap must
-///   be valid.
+/// [the reference]: https://doc.rust-lang.org/reference/destructors.html
 ///
-/// * While `async_drop_in_place` is executing or the returned async
-///   destructor is alive, the only way to access parts of `to_drop`
-///   is through the `self: Pin<&mut Self>` references supplied to
-///   the `AsyncDrop::async_drop` methods that `async_drop_in_place`
-///   or `AsyncDropInPlace<T>::poll` invokes. This usually means the
-///   returned future stores the `to_drop` pointer and user is required
-///   to guarantee that dropped value doesn't move.
+/// ## `Copy` and ([`Drop`]|`AsyncDrop`) are exclusive
 ///
-#[unstable(feature = "async_drop", issue = "126482")]
-pub unsafe fn async_drop_in_place<T: ?Sized>(to_drop: *mut T) -> AsyncDropInPlace<T> {
-    // SAFETY: `async_drop_in_place_raw` has the same safety requirements
-    unsafe { AsyncDropInPlace(async_drop_in_place_raw(to_drop)) }
-}
-
-/// A future returned by the [`async_drop_in_place`].
-#[unstable(feature = "async_drop", issue = "126482")]
-pub struct AsyncDropInPlace<T: ?Sized>(<T as AsyncDestruct>::AsyncDestructor);
-
-#[unstable(feature = "async_drop", issue = "126482")]
-impl<T: ?Sized> fmt::Debug for AsyncDropInPlace<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("AsyncDropInPlace").finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "async_drop", issue = "126482")]
-impl<T: ?Sized> Future for AsyncDropInPlace<T> {
-    type Output = ();
-
-    #[inline(always)]
-    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
-        // SAFETY: This code simply forwards poll call to the inner future
-        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) }.poll(cx)
-    }
-}
-
-// FIXME(zetanumbers): Add same restrictions on AsyncDrop impls as
-//   with Drop impls
-/// Custom code within the asynchronous destructor.
+/// You cannot implement both [`Copy`] and ([`Drop`]|`AsyncDrop`) on the same type. Types that
+/// are `Copy` get implicitly duplicated by the compiler, making it very
+/// hard to predict when, and how often destructors will be executed. As such,
+/// these types cannot have destructors.
+#[cfg(not(bootstrap))]
 #[unstable(feature = "async_drop", issue = "126482")]
 #[lang = "async_drop"]
 pub trait AsyncDrop {
-    /// A future returned by the [`AsyncDrop::async_drop`] to be part
-    /// of the async destructor.
-    #[unstable(feature = "async_drop", issue = "126482")]
-    type Dropper<'a>: Future<Output = ()>
-    where
-        Self: 'a;
-
-    /// Constructs the asynchronous destructor for this type.
-    #[unstable(feature = "async_drop", issue = "126482")]
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_>;
-}
-
-#[lang = "async_destruct"]
-#[rustc_deny_explicit_impl]
-#[rustc_do_not_implement_via_object]
-trait AsyncDestruct {
-    type AsyncDestructor: Future<Output = ()>;
-}
-
-/// Basically calls `AsyncDrop::async_drop` with pointer. Used to simplify
-/// generation of the code for `async_drop_in_place_raw`
-#[lang = "surface_async_drop_in_place"]
-async unsafe fn surface_async_drop_in_place<T: AsyncDrop + ?Sized>(ptr: *mut T) {
-    // SAFETY: We call this from async drop `async_drop_in_place_raw`
-    //   which has the same safety requirements
-    unsafe { <T as AsyncDrop>::async_drop(Pin::new_unchecked(&mut *ptr)).await }
-}
-
-/// Basically calls `Drop::drop` with pointer. Used to simplify generation
-/// of the code for `async_drop_in_place_raw`
-#[allow(drop_bounds)]
-#[lang = "async_drop_surface_drop_in_place"]
-async unsafe fn surface_drop_in_place<T: Drop + ?Sized>(ptr: *mut T) {
-    // SAFETY: We call this from async drop `async_drop_in_place_raw`
-    //   which has the same safety requirements
-    unsafe { crate::ops::fallback_surface_drop(&mut *ptr) }
-}
-
-/// Wraps a future to continue outputting `Poll::Ready(())` once after
-/// wrapped future completes by returning `Poll::Ready(())` on poll. This
-/// is useful for constructing async destructors to guarantee this
-/// "fuse" property
-//
-// FIXME: Consider optimizing combinators to not have to use fuse in majority
-// of cases, perhaps by adding `#[(rustc_)idempotent(_future)]` attribute for
-// async functions and blocks with the unit return type. However current layout
-// optimizations currently encode `None` case into the async block's discriminant.
-struct Fuse<T> {
-    inner: Option<T>,
-}
-
-#[lang = "async_drop_fuse"]
-fn fuse<T>(inner: T) -> Fuse<T> {
-    Fuse { inner: Some(inner) }
-}
-
-impl<T> Future for Fuse<T>
-where
-    T: Future<Output = ()>,
-{
-    type Output = ();
-
-    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
-        // SAFETY: pin projection into `self.inner`
-        unsafe {
-            let this = self.get_unchecked_mut();
-            if let Some(inner) = &mut this.inner {
-                ready!(Pin::new_unchecked(inner).poll(cx));
-                this.inner = None;
-            }
-        }
-        Poll::Ready(())
-    }
-}
-
-/// Async destructor for arrays and slices.
-#[lang = "async_drop_slice"]
-async unsafe fn slice<T>(s: *mut [T]) {
-    let len = s.len();
-    let ptr = s.as_mut_ptr();
-    for i in 0..len {
-        // SAFETY: we iterate over elements of `s` slice
-        unsafe { async_drop_in_place_raw(ptr.add(i)).await }
-    }
-}
-
-/// Constructs a chain of two futures, which awaits them sequentially as
-/// a future.
-#[lang = "async_drop_chain"]
-async fn chain<F, G>(first: F, last: G)
-where
-    F: IntoFuture<Output = ()>,
-    G: IntoFuture<Output = ()>,
-{
-    first.await;
-    last.await;
-}
-
-/// Basically a lazy version of `async_drop_in_place`. Returns a future
-/// that would call `AsyncDrop::async_drop` on a first poll.
-///
-/// # Safety
-///
-/// Same as `async_drop_in_place` except is lazy to avoid creating
-/// multiple mutable references.
-#[lang = "async_drop_defer"]
-async unsafe fn defer<T: ?Sized>(to_drop: *mut T) {
-    // SAFETY: same safety requirements as `async_drop_in_place`
-    unsafe { async_drop_in_place(to_drop) }.await
-}
-
-/// If `T`'s discriminant is equal to the stored one then awaits `M`
-/// otherwise awaits the `O`.
-///
-/// # Safety
-///
-/// Users should carefully manage the returned future, since it would
-/// try creating an immutable reference from `this` and get pointee's
-/// discriminant.
-// FIXME(zetanumbers): Send and Sync impls
-#[lang = "async_drop_either"]
-async unsafe fn either<O: IntoFuture<Output = ()>, M: IntoFuture<Output = ()>, T>(
-    other: O,
-    matched: M,
-    this: *mut T,
-    discr: <T as DiscriminantKind>::Discriminant,
-) {
-    // SAFETY: Guaranteed by the safety section of this funtion's documentation
-    if unsafe { discriminant_value(&*this) } == discr {
-        drop(other);
-        matched.await
-    } else {
-        drop(matched);
-        other.await
-    }
-}
-
-#[lang = "async_drop_deferred_drop_in_place"]
-async unsafe fn deferred_drop_in_place<T>(to_drop: *mut T) {
-    // SAFETY: same safety requirements as with drop_in_place (implied by
-    // function's name)
-    unsafe { crate::ptr::drop_in_place(to_drop) }
-}
-
-/// Used for noop async destructors. We don't use [`core::future::Ready`]
-/// because it panics after its second poll, which could be potentially
-/// bad if that would happen during the cleanup.
-#[derive(Clone, Copy)]
-struct Noop;
-
-#[lang = "async_drop_noop"]
-fn noop() -> Noop {
-    Noop
-}
-
-impl Future for Noop {
-    type Output = ();
-
-    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
-        Poll::Ready(())
-    }
+    /// Executes the async destructor for this type.
+    ///
+    /// This method is called implicitly when the value goes out of scope,
+    /// and cannot be called explicitly.
+    ///
+    /// When this method has been called, `self` has not yet been deallocated.
+    /// That only happens after the method is over.
+    ///
+    /// # Panics
+    #[allow(async_fn_in_trait)]
+    async fn drop(self: Pin<&mut Self>);
+}
+
+/// Async drop.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "async_drop", issue = "126482")]
+#[lang = "async_drop_in_place"]
+pub async unsafe fn async_drop_in_place<T: ?Sized>(_to_drop: *mut T) {
+    // Code here does not matter - this is replaced by the
+    // real implementation by the compiler.
 }
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 65c0171c88d..4b5a2f34d3f 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -20,8 +20,9 @@ mod pending;
 mod poll_fn;
 mod ready;
 
+#[cfg(not(bootstrap))]
 #[unstable(feature = "async_drop", issue = "126482")]
-pub use async_drop::{AsyncDrop, AsyncDropInPlace, async_drop, async_drop_in_place};
+pub use async_drop::{AsyncDrop, async_drop_in_place};
 #[stable(feature = "into_future", since = "1.64.0")]
 pub use into_future::IntoFuture;
 #[stable(feature = "future_readiness_fns", since = "1.48.0")]
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index a7563f918a2..c5d5bc000f1 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2996,7 +2996,7 @@ pub unsafe fn nontemporal_store<T>(ptr: *mut T, val: T);
 #[rustc_intrinsic]
 pub const unsafe fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
-/// See documentation of `<*const T>::sub_ptr` for details.
+/// See documentation of `<*const T>::offset_from_unsigned` for details.
 #[rustc_nounwind]
 #[rustc_intrinsic]
 #[rustc_intrinsic_const_stable_indirect]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9625475e617..64a7ec8906b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -118,7 +118,6 @@
 #![feature(ptr_metadata)]
 #![feature(set_ptr_value)]
 #![feature(slice_as_array)]
-#![feature(slice_as_chunks)]
 #![feature(slice_ptr_get)]
 #![feature(str_internals)]
 #![feature(str_split_inclusive_remainder)]
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index e024b7fb4d3..5d040804a8d 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -240,10 +240,3 @@ pub trait Drop {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
-
-/// Fallback function to call surface level `Drop::drop` function
-#[allow(drop_bounds)]
-#[lang = "fallback_surface_drop"]
-pub(crate) fn fallback_surface_drop<T: Drop + ?Sized>(x: &mut T) {
-    <T as Drop>::drop(x)
-}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 627a875d9f7..1658f0e5a36 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -176,7 +176,6 @@ pub use self::deref::Receiver;
 pub use self::deref::{Deref, DerefMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::drop::Drop;
-pub(crate) use self::drop::fallback_surface_drop;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::function::{Fn, FnMut, FnOnce};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 33ad59916e3..83a45436b30 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -155,30 +155,26 @@ pub const fn panic(expr: &'static str) -> ! {
 // reducing binary size impact.
 macro_rules! panic_const {
     ($($lang:ident = $message:expr,)+) => {
-        pub mod panic_const {
-            use super::*;
-
-            $(
-                /// This is a panic called with a message that's a result of a MIR-produced Assert.
-                //
-                // never inline unless panic_immediate_abort to avoid code
-                // bloat at the call sites as much as possible
-                #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-                #[cfg_attr(feature = "panic_immediate_abort", inline)]
-                #[track_caller]
-                #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
-                #[lang = stringify!($lang)]
-                pub const fn $lang() -> ! {
-                    // Use Arguments::new_const instead of format_args!("{expr}") to potentially
-                    // reduce size overhead. The format_args! macro uses str's Display trait to
-                    // write expr, which calls Formatter::pad, which must accommodate string
-                    // truncation and padding (even though none is used here). Using
-                    // Arguments::new_const may allow the compiler to omit Formatter::pad from the
-                    // output binary, saving up to a few kilobytes.
-                    panic_fmt(fmt::Arguments::new_const(&[$message]));
-                }
-            )+
-        }
+        $(
+            /// This is a panic called with a message that's a result of a MIR-produced Assert.
+            //
+            // never inline unless panic_immediate_abort to avoid code
+            // bloat at the call sites as much as possible
+            #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+            #[cfg_attr(feature = "panic_immediate_abort", inline)]
+            #[track_caller]
+            #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
+            #[lang = stringify!($lang)]
+            pub const fn $lang() -> ! {
+                // Use Arguments::new_const instead of format_args!("{expr}") to potentially
+                // reduce size overhead. The format_args! macro uses str's Display trait to
+                // write expr, which calls Formatter::pad, which must accommodate string
+                // truncation and padding (even though none is used here). Using
+                // Arguments::new_const may allow the compiler to omit Formatter::pad from the
+                // output binary, saving up to a few kilobytes.
+                panic_fmt(fmt::Arguments::new_const(&[$message]));
+            }
+        )+
     }
 }
 
@@ -186,25 +182,37 @@ macro_rules! panic_const {
 // slightly different forms. It's not clear if there's a good way to deduplicate without adding
 // special cases to the compiler (e.g., a const generic function wouldn't have a single definition
 // shared across crates, which is exactly what we want here).
-panic_const! {
-    panic_const_add_overflow = "attempt to add with overflow",
-    panic_const_sub_overflow = "attempt to subtract with overflow",
-    panic_const_mul_overflow = "attempt to multiply with overflow",
-    panic_const_div_overflow = "attempt to divide with overflow",
-    panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
-    panic_const_neg_overflow = "attempt to negate with overflow",
-    panic_const_shr_overflow = "attempt to shift right with overflow",
-    panic_const_shl_overflow = "attempt to shift left with overflow",
-    panic_const_div_by_zero = "attempt to divide by zero",
-    panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
-    panic_const_coroutine_resumed = "coroutine resumed after completion",
-    panic_const_async_fn_resumed = "`async fn` resumed after completion",
-    panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion",
-    panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion",
-    panic_const_coroutine_resumed_panic = "coroutine resumed after panicking",
-    panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking",
-    panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking",
-    panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking",
+pub mod panic_const {
+    use super::*;
+    panic_const! {
+        panic_const_add_overflow = "attempt to add with overflow",
+        panic_const_sub_overflow = "attempt to subtract with overflow",
+        panic_const_mul_overflow = "attempt to multiply with overflow",
+        panic_const_div_overflow = "attempt to divide with overflow",
+        panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
+        panic_const_neg_overflow = "attempt to negate with overflow",
+        panic_const_shr_overflow = "attempt to shift right with overflow",
+        panic_const_shl_overflow = "attempt to shift left with overflow",
+        panic_const_div_by_zero = "attempt to divide by zero",
+        panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
+        panic_const_coroutine_resumed = "coroutine resumed after completion",
+        panic_const_async_fn_resumed = "`async fn` resumed after completion",
+        panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion",
+        panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion",
+        panic_const_coroutine_resumed_panic = "coroutine resumed after panicking",
+        panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking",
+        panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking",
+        panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking",
+    }
+    // Separated panic constants list for async drop feature
+    // (May be joined when the corresponding lang items will be in the bootstrap)
+    #[cfg(not(bootstrap))]
+    panic_const! {
+        panic_const_coroutine_resumed_drop = "coroutine resumed after async drop",
+        panic_const_async_fn_resumed_drop = "`async fn` resumed after async drop",
+        panic_const_async_gen_fn_resumed_drop = "`async gen fn` resumed after async drop",
+        panic_const_gen_fn_none_drop = "`gen fn` resumed after async drop",
+    }
 }
 
 /// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 2d869958b85..bcf34781c8a 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -804,8 +804,8 @@ impl<T: ?Sized> *const T {
     /// units of **bytes**.
     ///
     /// This is purely a convenience for casting to a `u8` pointer and
-    /// using [`sub_ptr`][pointer::offset_from_unsigned] on it. See that method for
-    /// documentation and safety requirements.
+    /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it.
+    /// See that method for documentation and safety requirements.
     ///
     /// For non-`Sized` pointees this operation considers only the data pointers,
     /// ignoring the metadata.
@@ -814,7 +814,7 @@ impl<T: ?Sized> *const T {
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *const U) -> usize {
-        // SAFETY: the caller must uphold the safety contract for `sub_ptr`.
+        // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`.
         unsafe { self.cast::<u8>().offset_from_unsigned(origin.cast::<u8>()) }
     }
 
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index df49eedb350..6d1a50d8436 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -937,6 +937,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// // This would be incorrect, as the pointers are not correctly ordered:
     /// // ptr1.offset_from(ptr2)
+    /// ```
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     #[inline]
@@ -945,7 +946,7 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
-        // SAFETY: the caller must uphold the safety contract for `sub_ptr`.
+        // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`.
         unsafe { (self as *const T).offset_from_unsigned(origin) }
     }
 
@@ -954,8 +955,8 @@ impl<T: ?Sized> *mut T {
     /// units of **bytes**.
     ///
     /// This is purely a convenience for casting to a `u8` pointer and
-    /// using [`sub_ptr`][pointer::offset_from_unsigned] on it. See that method for
-    /// documentation and safety requirements.
+    /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it.
+    /// See that method for documentation and safety requirements.
     ///
     /// For non-`Sized` pointees this operation considers only the data pointers,
     /// ignoring the metadata.
@@ -964,7 +965,7 @@ impl<T: ?Sized> *mut T {
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *mut U) -> usize {
-        // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
+        // SAFETY: the caller must uphold the safety contract for `byte_offset_from_unsigned`.
         unsafe { (self as *const T).byte_offset_from_unsigned(origin) }
     }
 
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 68b8f0c3e4e..0864cc457b6 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -906,7 +906,7 @@ impl<T: ?Sized> NonNull<T> {
     where
         T: Sized,
     {
-        // SAFETY: the caller must uphold the safety contract for `sub_ptr`.
+        // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`.
         unsafe { self.as_ptr().offset_from_unsigned(subtracted.as_ptr()) }
     }
 
@@ -915,8 +915,8 @@ impl<T: ?Sized> NonNull<T> {
     /// units of **bytes**.
     ///
     /// This is purely a convenience for casting to a `u8` pointer and
-    /// using [`sub_ptr`][NonNull::offset_from_unsigned] on it. See that method for
-    /// documentation and safety requirements.
+    /// using [`offset_from_unsigned`][NonNull::offset_from_unsigned] on it.
+    /// See that method for documentation and safety requirements.
     ///
     /// For non-`Sized` pointees this operation considers only the data pointers,
     /// ignoring the metadata.
@@ -925,7 +925,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: NonNull<U>) -> usize {
-        // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
+        // SAFETY: the caller must uphold the safety contract for `byte_offset_from_unsigned`.
         unsafe { self.as_ptr().byte_offset_from_unsigned(origin.as_ptr()) }
     }
 
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index f507ee563ac..85a5e89a49e 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -2335,7 +2335,6 @@ pub struct ArrayChunks<'a, T: 'a, const N: usize> {
 
 impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
     #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
-    // #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     pub(super) const fn new(slice: &'a [T]) -> Self {
         let (array_slice, rem) = slice.as_chunks();
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index fbfa4d87415..81fe0166fd7 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1268,6 +1268,18 @@ impl<T> [T] {
     /// Splits the slice into a slice of `N`-element arrays,
     /// assuming that there's no remainder.
     ///
+    /// This is the inverse operation to [`as_flattened`].
+    ///
+    /// [`as_flattened`]: slice::as_flattened
+    ///
+    /// As this is `unsafe`, consider whether you could use [`as_chunks`] or
+    /// [`as_rchunks`] instead, perhaps via something like
+    /// `if let (chunks, []) = slice.as_chunks()` or
+    /// `let (chunks, []) = slice.as_chunks() else { unreachable!() };`.
+    ///
+    /// [`as_chunks`]: slice::as_chunks
+    /// [`as_rchunks`]: slice::as_rchunks
+    ///
     /// # Safety
     ///
     /// This may only be called when
@@ -1277,7 +1289,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
     /// let chunks: &[[char; 1]] =
     ///     // SAFETY: 1-element chunks never have remainder
@@ -1292,7 +1303,8 @@ impl<T> [T] {
     /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
     /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[must_use]
     pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
@@ -1312,15 +1324,27 @@ impl<T> [T] {
     /// starting at the beginning of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
+    /// The remainder is meaningful in the division sense.  Given
+    /// `let (chunks, remainder) = slice.as_chunks()`, then:
+    /// - `chunks.len()` equals `slice.len() / N`,
+    /// - `remainder.len()` equals `slice.len() % N`, and
+    /// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
+    ///
+    /// You can flatten the chunks back into a slice-of-`T` with [`as_flattened`].
+    ///
+    /// [`as_flattened`]: slice::as_flattened
+    ///
     /// # Panics
     ///
-    /// Panics if `N` is zero. This check will most probably get changed to a compile time
-    /// error before this method gets stabilized.
+    /// Panics if `N` is zero.
+    ///
+    /// Note that this check is against a const generic parameter, not a runtime
+    /// value, and thus a particular monomorphization will either always panic
+    /// or it will never panic.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
     /// let (chunks, remainder) = slice.as_chunks();
     /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
@@ -1330,14 +1354,14 @@ impl<T> [T] {
     /// If you expect the slice to be an exact multiple, you can combine
     /// `let`-`else` with an empty slice pattern:
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let slice = ['R', 'u', 's', 't'];
     /// let (chunks, []) = slice.as_chunks::<2>() else {
     ///     panic!("slice didn't have even length")
     /// };
     /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[track_caller]
     #[must_use]
@@ -1357,21 +1381,34 @@ impl<T> [T] {
     /// starting at the end of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
+    /// The remainder is meaningful in the division sense.  Given
+    /// `let (remainder, chunks) = slice.as_rchunks()`, then:
+    /// - `remainder.len()` equals `slice.len() % N`,
+    /// - `chunks.len()` equals `slice.len() / N`, and
+    /// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
+    ///
+    /// You can flatten the chunks back into a slice-of-`T` with [`as_flattened`].
+    ///
+    /// [`as_flattened`]: slice::as_flattened
+    ///
     /// # Panics
     ///
-    /// Panics if `N` is zero. This check will most probably get changed to a compile time
-    /// error before this method gets stabilized.
+    /// Panics if `N` is zero.
+    ///
+    /// Note that this check is against a const generic parameter, not a runtime
+    /// value, and thus a particular monomorphization will either always panic
+    /// or it will never panic.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
     /// let (remainder, chunks) = slice.as_rchunks();
     /// assert_eq!(remainder, &['l']);
     /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[track_caller]
     #[must_use]
@@ -1424,6 +1461,18 @@ impl<T> [T] {
     /// Splits the slice into a slice of `N`-element arrays,
     /// assuming that there's no remainder.
     ///
+    /// This is the inverse operation to [`as_flattened_mut`].
+    ///
+    /// [`as_flattened_mut`]: slice::as_flattened_mut
+    ///
+    /// As this is `unsafe`, consider whether you could use [`as_chunks_mut`] or
+    /// [`as_rchunks_mut`] instead, perhaps via something like
+    /// `if let (chunks, []) = slice.as_chunks_mut()` or
+    /// `let (chunks, []) = slice.as_chunks_mut() else { unreachable!() };`.
+    ///
+    /// [`as_chunks_mut`]: slice::as_chunks_mut
+    /// [`as_rchunks_mut`]: slice::as_rchunks_mut
+    ///
     /// # Safety
     ///
     /// This may only be called when
@@ -1433,7 +1482,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
     /// let chunks: &mut [[char; 1]] =
     ///     // SAFETY: 1-element chunks never have remainder
@@ -1450,7 +1498,8 @@ impl<T> [T] {
     /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
     /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[must_use]
     pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
@@ -1470,15 +1519,27 @@ impl<T> [T] {
     /// starting at the beginning of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
+    /// The remainder is meaningful in the division sense.  Given
+    /// `let (chunks, remainder) = slice.as_chunks_mut()`, then:
+    /// - `chunks.len()` equals `slice.len() / N`,
+    /// - `remainder.len()` equals `slice.len() % N`, and
+    /// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
+    ///
+    /// You can flatten the chunks back into a slice-of-`T` with [`as_flattened_mut`].
+    ///
+    /// [`as_flattened_mut`]: slice::as_flattened_mut
+    ///
     /// # Panics
     ///
-    /// Panics if `N` is zero. This check will most probably get changed to a compile time
-    /// error before this method gets stabilized.
+    /// Panics if `N` is zero.
+    ///
+    /// Note that this check is against a const generic parameter, not a runtime
+    /// value, and thus a particular monomorphization will either always panic
+    /// or it will never panic.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -1490,7 +1551,8 @@ impl<T> [T] {
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 9]);
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[track_caller]
     #[must_use]
@@ -1510,15 +1572,27 @@ impl<T> [T] {
     /// starting at the end of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
+    /// The remainder is meaningful in the division sense.  Given
+    /// `let (remainder, chunks) = slice.as_rchunks_mut()`, then:
+    /// - `remainder.len()` equals `slice.len() % N`,
+    /// - `chunks.len()` equals `slice.len() / N`, and
+    /// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
+    ///
+    /// You can flatten the chunks back into a slice-of-`T` with [`as_flattened_mut`].
+    ///
+    /// [`as_flattened_mut`]: slice::as_flattened_mut
+    ///
     /// # Panics
     ///
-    /// Panics if `N` is zero. This check will most probably get changed to a compile time
-    /// error before this method gets stabilized.
+    /// Panics if `N` is zero.
+    ///
+    /// Note that this check is against a const generic parameter, not a runtime
+    /// value, and thus a particular monomorphization will either always panic
+    /// or it will never panic.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_as_chunks)]
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -1530,7 +1604,8 @@ impl<T> [T] {
     /// }
     /// assert_eq!(v, &[9, 1, 1, 2, 2]);
     /// ```
-    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     #[track_caller]
     #[must_use]
@@ -4816,6 +4891,11 @@ impl<T> [MaybeUninit<T>] {
 impl<T, const N: usize> [[T; N]] {
     /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
     ///
+    /// For the opposite operation, see [`as_chunks`] and [`as_rchunks`].
+    ///
+    /// [`as_chunks`]: slice::as_chunks
+    /// [`as_rchunks`]: slice::as_rchunks
+    ///
     /// # Panics
     ///
     /// This panics if the length of the resulting slice would overflow a `usize`.
@@ -4856,6 +4936,11 @@ impl<T, const N: usize> [[T; N]] {
 
     /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`.
     ///
+    /// For the opposite operation, see [`as_chunks_mut`] and [`as_rchunks_mut`].
+    ///
+    /// [`as_chunks_mut`]: slice::as_chunks_mut
+    /// [`as_rchunks_mut`]: slice::as_rchunks_mut
+    ///
     /// # Panics
     ///
     /// This panics if the length of the resulting slice would overflow a `usize`.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 602af4a0447..940b671c514 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/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/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};