diff --git a/library/core/src/primitive.rs b/library/core/src/primitive.rs
deleted file mode 100644
index e20b2c5c9382a..0000000000000
--- a/library/core/src/primitive.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! This module reexports the primitive types to allow usage that is not
-//! possibly shadowed by other declared types.
-//!
-//! This is normally only useful in macro generated code.
-//!
-//! An example of this is when generating a new struct and an impl for it:
-//!
-//! ```rust,compile_fail
-//! pub struct bool;
-//!
-//! impl QueryId for bool {
-//!     const SOME_PROPERTY: bool = true;
-//! }
-//!
-//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
-//! ```
-//!
-//! Note that the `SOME_PROPERTY` associated constant would not compile, as its
-//! type `bool` refers to the struct, rather than to the primitive bool type.
-//!
-//! A correct implementation could look like:
-//!
-//! ```rust
-//! # #[allow(non_camel_case_types)]
-//! pub struct bool;
-//!
-//! impl QueryId for bool {
-//!     const SOME_PROPERTY: core::primitive::bool = true;
-//! }
-//!
-//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
-//! ```
-
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use bool;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use char;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use f32;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use f64;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use i128;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use i16;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use i32;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use i64;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use i8;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use isize;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use str;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use u128;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use u16;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use u32;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use u64;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use u8;
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use usize;
diff --git a/library/core/src/primitive/float_macros.rs b/library/core/src/primitive/float_macros.rs
new file mode 100644
index 0000000000000..2a82ff603d97e
--- /dev/null
+++ b/library/core/src/primitive/float_macros.rs
@@ -0,0 +1,44 @@
+// Note: currently limiting this to what f16/f128 already support (which isn't much).
+// f32/f64 share essentially their whole API which should be added here eventually.
+
+macro_rules! float_decl {
+    () => {
+        /// Returns `true` if this value is NaN.
+        fn is_nan(self) -> bool;
+
+        /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
+        /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any
+        /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
+        /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
+        /// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
+        /// See [explanation of NaN as a special value](f32) for more info.
+        fn is_sign_positive(self) -> bool;
+
+        /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
+        /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any
+        /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
+        /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
+        /// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
+        /// See [explanation of NaN as a special value](f32) for more info.
+        fn is_sign_negative(self) -> bool;
+    };
+}
+
+macro_rules! float_impl {
+    () => {
+        #[inline]
+        fn is_nan(self) -> bool {
+            Self::is_nan(self)
+        }
+
+        #[inline]
+        fn is_sign_positive(self) -> bool {
+            Self::is_sign_positive(self)
+        }
+
+        #[inline]
+        fn is_sign_negative(self) -> bool {
+            Self::is_sign_negative(self)
+        }
+    };
+}
diff --git a/library/core/src/primitive/int_macros.rs b/library/core/src/primitive/int_macros.rs
new file mode 100644
index 0000000000000..0dd774e48dd93
--- /dev/null
+++ b/library/core/src/primitive/int_macros.rs
@@ -0,0 +1,880 @@
+macro_rules! int_decl {
+    () => {
+        /// The smallest value that can be represented by this integer type.
+        const MIN: Self;
+
+        /// The largest value that can be represented by this integer type.
+        const MAX: Self;
+
+        /// The size of this integer type in bits.
+        const BITS: u32;
+
+        /// Returns the number of zeros in the binary representation of `self`.
+        fn count_ones(self) -> u32;
+
+        /// Returns the number of zeros in the binary representation of `self`.
+        fn count_zeros(self) -> u32;
+
+        /// Returns the number of leading zeros in the binary representation of `self`.
+        ///
+        /// Depending on what you're doing with the value, you might also be interested in the
+        /// [`ilog2`] function which returns a consistent number, even if the type widens.
+        fn leading_zeros(self) -> u32;
+
+        /// Returns the number of trailing zeros in the binary representation of `self`.
+        fn trailing_zeros(self) -> u32;
+
+        /// Returns the number of leading ones in the binary representation of `self`.
+        fn leading_ones(self) -> u32;
+
+        /// Returns the number of trailing ones in the binary representation of `self`.
+        fn trailing_ones(self) -> u32;
+
+        /// Shifts the bits to the left by a specified amount, `n`,
+        /// wrapping the truncated bits to the end of the resulting integer.
+        ///
+        /// Please note this isn't the same operation as the `<<` shifting operator!
+        fn rotate_left(self, n: u32) -> Self;
+
+        /// Shifts the bits to the right by a specified amount, `n`,
+        /// wrapping the truncated bits to the beginning of the resulting
+        /// integer.
+        ///
+        /// Please note this isn't the same operation as the `>>` shifting operator!
+        fn rotate_right(self, n: u32) -> Self;
+
+        /// Reverses the byte order of the integer.
+        fn swap_bytes(self) -> Self;
+
+        /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+        ///                 second least-significant bit becomes second most-significant bit, etc.
+        fn reverse_bits(self) -> Self;
+
+        /// Converts an integer from big endian to the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are swapped.
+        fn from_be(x: Self) -> Self;
+
+        /// Converts an integer from little endian to the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are swapped.
+        fn from_le(x: Self) -> Self;
+
+        /// Converts `self` to big endian from the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are swapped.
+        fn to_be(self) -> Self;
+
+        /// Converts `self` to little endian from the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are swapped.
+        fn to_le(self) -> Self;
+
+        /// Checked integer addition. Computes `self + rhs`, returning `None`
+        /// if overflow occurred.
+        fn checked_add(self, rhs: Self) -> Option<Self>;
+
+        /// Strict integer addition. Computes `self + rhs`, panicking
+        /// if overflow occurred.
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        fn strict_add(self, rhs: Self) -> Self;
+
+        /// Unchecked integer addition. Computes `self + rhs`, assuming overflow
+        /// cannot occur.
+        ///
+        /// Calling `x.unchecked_add(y)` is semantically equivalent to calling
+        /// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`.
+        ///
+        /// If you're just trying to avoid the panic in debug mode, then **do not**
+        /// use this.  Instead, you're looking for [`wrapping_add`].
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `self + rhs > Self::MAX` or
+        /// `self + rhs < Self::MIN`, i.e. when [`checked_add`] would return `None`.
+        unsafe fn unchecked_add(self, rhs: Self) -> Self;
+
+        /// Checked integer subtraction. Computes `self - rhs`, returning `None` if
+        /// overflow occurred.
+        fn checked_sub(self, rhs: Self) -> Option<Self>;
+
+        /// Strict integer subtraction. Computes `self - rhs`, panicking if
+        /// overflow occurred.
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        fn strict_sub(self, rhs: Self) -> Self;
+
+        /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
+        /// cannot occur.
+        ///
+        /// Calling `x.unchecked_sub(y)` is semantically equivalent to calling
+        /// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`.
+        ///
+        /// If you're just trying to avoid the panic in debug mode, then **do not**
+        /// use this.  Instead, you're looking for [`wrapping_sub`].
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `self - rhs > Self::MAX` or
+        /// `self - rhs < Self::MIN`, i.e. when [`checked_sub`] would return `None`.
+        unsafe fn unchecked_sub(self, rhs: Self) -> Self;
+
+        /// Checked integer multiplication. Computes `self * rhs`, returning `None` if
+        /// overflow occurred.
+        fn checked_mul(self, rhs: Self) -> Option<Self>;
+
+        /// Strict integer multiplication. Computes `self * rhs`, panicking if
+        /// overflow occurred.
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        fn strict_mul(self, rhs: Self) -> Self;
+
+        /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
+        /// cannot occur.
+        ///
+        /// Calling `x.unchecked_mul(y)` is semantically equivalent to calling
+        /// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`.
+        ///
+        /// If you're just trying to avoid the panic in debug mode, then **do not**
+        /// use this.  Instead, you're looking for [`wrapping_mul`].
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `self * rhs > Self::MAX` or
+        /// `self * rhs < Self::MIN`, i.e. when [`checked_mul`] would return `None`.
+        unsafe fn unchecked_mul(self, rhs: Self) -> Self;
+
+        /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
+        /// or the division results in overflow.
+        fn checked_div(self, rhs: Self) -> Option<Self>;
+
+        /// Strict integer division. Computes `self / rhs`, panicking
+        /// if overflow occurred.
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        fn strict_div(self, rhs: Self) -> Self;
+
+        /// Checked Euclidean division. Computes `self.div_euclid(rhs)`,
+        /// returning `None` if `rhs == 0` or the division results in overflow.
+        fn checked_div_euclid(self, rhs: Self) -> Option<Self>;
+
+        /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking
+        /// if overflow occurred.
+        fn strict_div_euclid(self, rhs: Self) -> Self;
+
+        /// Checked integer remainder. Computes `self % rhs`, returning `None` if
+        /// `rhs == 0` or the division results in overflow.
+        fn checked_rem(self, rhs: Self) -> Option<Self>;
+
+        /// Strict integer remainder. Computes `self % rhs`, panicking if
+        /// the division results in overflow.
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        fn strict_rem(self, rhs: Self) -> Self;
+
+        /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
+        /// if `rhs == 0` or the division results in overflow.
+        fn checked_rem_euclid(self, rhs: Self) -> Option<Self>;
+
+        /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if
+        /// the division results in overflow.
+        fn strict_rem_euclid(self, rhs: Self) -> Self;
+
+        /// Checked negation. Computes `-self`, returning `None` if the result is `< MIN`.
+        fn checked_neg(self) -> Option<Self>;
+
+        /// Strict negation. Computes `-self`, panicking if the result is `< MIN`.
+        fn strict_neg(self) -> Self;
+
+        /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
+        /// than or equal to the number of bits in `self`.
+        fn checked_shl(self, rhs: u32) -> Option<Self>;
+
+        /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger
+        /// than or equal to the number of bits in `self`.
+        fn strict_shl(self, rhs: u32) -> Self;
+
+        /// Unchecked shift left. Computes `self << rhs`, assuming that
+        /// `rhs` is less than the number of bits in `self`.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior if `rhs` is larger than
+        /// or equal to the number of bits in `self`,
+        /// i.e. when [`checked_shl`] would return `None`.
+        unsafe fn unchecked_shl(self, rhs: u32) -> Self;
+
+        /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
+        /// larger than or equal to the number of bits in `self`.
+        fn checked_shr(self, rhs: u32) -> Option<Self>;
+
+        /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is
+        /// larger than or equal to the number of bits in `self`.
+        fn strict_shr(self, rhs: u32) -> Self;
+
+        /// Unchecked shift right. Computes `self >> rhs`, assuming that
+        /// `rhs` is less than the number of bits in `self`.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior if `rhs` is larger than
+        /// or equal to the number of bits in `self`,
+        /// i.e. when [`checked_shr`] would return `None`.
+        unsafe fn unchecked_shr(self, rhs: u32) -> Self;
+
+        /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
+        /// overflow occurred.
+        fn checked_pow(self, exp: u32) -> Option<Self>;
+
+        /// Strict exponentiation. Computes `self.pow(exp)`, panicking if
+        /// overflow occurred.
+        fn strict_pow(self, exp: u32) -> Self;
+
+        /// Saturating integer addition. Computes `self + rhs`, saturating at
+        /// the numeric bounds instead of overflowing.
+        fn saturating_add(self, rhs: Self) -> Self;
+
+        /// Saturating integer subtraction. Computes `self - rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        fn saturating_sub(self, rhs: Self) -> Self;
+
+        /// Saturating integer multiplication. Computes `self * rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        fn saturating_mul(self, rhs: Self) -> Self;
+
+        /// Saturating integer division. Computes `self / rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        fn saturating_div(self, rhs: Self) -> Self;
+
+        /// Saturating integer exponentiation. Computes `self.pow(exp)`,
+        /// saturating at the numeric bounds instead of overflowing.
+        fn saturating_pow(self, exp: u32) -> Self;
+
+        /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
+        /// boundary of the type.
+        fn wrapping_add(self, rhs: Self) -> Self;
+
+        /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
+        /// boundary of the type.
+        fn wrapping_sub(self, rhs: Self) -> Self;
+
+        /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
+        /// the boundary of the type.
+        fn wrapping_mul(self, rhs: Self) -> Self;
+
+        /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where
+        /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
+        /// that is too large to represent in the type. In such a case, this function returns `MIN` itself.
+        fn wrapping_div(self, rhs: Self) -> Self;
+
+        /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
+        /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the
+        /// type. In this case, this method returns `MIN` itself.
+        fn wrapping_div_euclid(self, rhs: Self) -> Self;
+
+        /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y`
+        /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case,
+        /// this function returns `0`.
+        fn wrapping_rem(self, rhs: Self) -> Self;
+
+        /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around
+        /// at the boundary of the type.
+        ///
+        /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
+        /// for the type). In this case, this method returns 0.
+        fn wrapping_rem_euclid(self, rhs: Self) -> Self;
+
+        /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+        /// of the type.
+        ///
+        /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN`
+        /// is the negative minimal value for the type); this is a positive value that is too large to represent
+        /// in the type. In such a case, this function returns `MIN` itself.
+        fn wrapping_neg(self) -> Self;
+
+        /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes
+        /// any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to
+        /// the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
+        /// The primitive integer types all implement a [`rotate_left`](Self::rotate_left) function,
+        /// which may be what you want instead.
+        fn wrapping_shl(self, rhs: u32) -> Self;
+
+        /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
+        /// where `mask` removes any high-order bits of `rhs` that
+        /// would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-right; the
+        /// RHS of a wrapping shift-right is restricted to the range
+        /// of the type, rather than the bits shifted out of the LHS
+        /// being returned to the other end. The primitive integer
+        /// types all implement a [`rotate_right`](Self::rotate_right) function,
+        /// which may be what you want instead.
+        fn wrapping_shr(self, rhs: u32) -> Self;
+
+        /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
+        /// wrapping around at the boundary of the type.
+        fn wrapping_pow(self, exp: u32) -> Self;
+
+        /// Calculates `self` + `rhs`
+        ///
+        /// Returns a tuple of the addition along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        fn overflowing_add(self, rhs: Self) -> (Self, bool);
+
+        /// Calculates `self` - `rhs`
+        ///
+        /// Returns a tuple of the subtraction along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        fn overflowing_sub(self, rhs: Self) -> (Self, bool);
+
+        /// Calculates the multiplication of `self` and `rhs`.
+        ///
+        /// Returns a tuple of the multiplication along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would have occurred then the wrapped value is returned.
+        fn overflowing_mul(self, rhs: Self) -> (Self, bool);
+
+        /// Calculates the divisor when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        ///  occur then self is returned.
+        fn overflowing_div(self, rhs: Self) -> (Self, bool);
+
+        /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        ///  occur then self is returned.
+        fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool);
+
+        /// Calculates the remainder when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would occur then 0 is returned.
+        fn overflowing_rem(self, rhs: Self) -> (Self, bool);
+
+        /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would occur then 0 is returned.
+        fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool);
+
+        /// Negates self, overflowing if this is equal to the minimum value.
+        ///
+        /// Returns a tuple of the negated version of self along with a boolean
+        /// indicating whether an overflow happened. If `self` is the minimum
+        /// signed value (e.g., `i32::MIN` for values of type `i32`), then the
+        /// minimum value will be returned again and `true` will be returned for
+        /// an overflow happening.
+        fn overflowing_neg(self) -> (Self, bool);
+
+        /// Shifts self left by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        fn overflowing_shl(self, rhs: u32) -> (Self, bool);
+
+        /// Shifts self right by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        fn overflowing_shr(self, rhs: u32) -> (Self, bool);
+
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        ///
+        /// Returns a tuple of the exponentiation along with a bool indicating
+        /// whether an overflow happened.
+        fn overflowing_pow(self, exp: u32) -> (Self, bool);
+
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        fn pow(self, exp: u32) -> Self;
+
+        /// Returns the square root of the number, rounded down.
+        #[unstable(feature = "isqrt", issue = "116226")]
+        fn isqrt(self) -> Self;
+
+        /// Calculates the quotient of Euclidean division of `self` by `rhs`.
+        ///
+        /// This computes the integer `q` such that `self = q * rhs + r`, with
+        /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`.
+        ///
+        /// In other words, the result is `self / rhs` rounded to the integer `q`
+        /// such that `self >= q * rhs`.
+        /// If `self > 0`, this is equal to round towards zero (the default in Rust);
+        /// if `self < 0`, this is equal to round towards +/- infinity.
+        fn div_euclid(self, rhs: Self) -> Self;
+
+        /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+        ///
+        /// This is done as if by the Euclidean division algorithm -- given
+        /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`,
+        /// and `0 <= r < abs(rhs)`.
+        fn rem_euclid(self, rhs: Self) -> Self;
+
+        /// Calculates the quotient of `self` and `rhs`, rounding the result
+        /// towards negative infinity.
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        fn div_floor(self, rhs: Self) -> Self;
+
+        /// Calculates the quotient of `self` and `rhs`, rounding the result
+        /// towards positive infinity.
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        fn div_ceil(self, rhs: Self) -> Self;
+
+        /// If `rhs` is positive, calculates the smallest value greater than or
+        /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
+        /// calculates the largest value less than or equal to `self` that is a
+        /// multiple of `rhs`.
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        fn next_multiple_of(self, rhs: Self) -> Self;
+
+        /// If `rhs` is positive, calculates the smallest value greater than or
+        /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
+        /// calculates the largest value less than or equal to `self` that is a
+        /// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation
+        /// would result in overflow.
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        fn checked_next_multiple_of(self, rhs: Self) -> Option<Self>;
+
+        /// Returns the smallest value that can be represented by this integer type.
+        ///
+        /// New code should prefer to use [`Self::MIN`] instead.
+        #[deprecated(
+            since = "TBD",
+            note = "replaced by the `MAX` associated constant on this type"
+        )]
+        fn min_value() -> Self;
+
+        /// Returns the largest value that can be represented by this integer type.
+        ///
+        /// New code should prefer to use [`Self::MAX`] instead.
+        #[deprecated(
+            since = "TBD",
+            note = "replaced by the `MAX` associated constant on this type"
+        )]
+        fn max_value() -> Self;
+    };
+}
+
+macro_rules! int_impl {
+    () => {
+        const MIN: Self = Self::MIN;
+        const MAX: Self = Self::MAX;
+        const BITS: u32 = Self::BITS;
+
+        #[inline]
+        fn count_ones(self) -> u32 {
+            Self::count_ones(self)
+        }
+
+        #[inline]
+        fn count_zeros(self) -> u32 {
+            Self::count_zeros(self)
+        }
+
+        #[inline]
+        fn leading_zeros(self) -> u32 {
+            Self::leading_zeros(self)
+        }
+
+        #[inline]
+        fn trailing_zeros(self) -> u32 {
+            Self::trailing_zeros(self)
+        }
+
+        #[inline]
+        fn leading_ones(self) -> u32 {
+            Self::leading_ones(self)
+        }
+
+        #[inline]
+        fn trailing_ones(self) -> u32 {
+            Self::trailing_ones(self)
+        }
+
+        #[inline]
+        fn rotate_left(self, n: u32) -> Self {
+            Self::rotate_left(self, n)
+        }
+
+        #[inline]
+        fn rotate_right(self, n: u32) -> Self {
+            Self::rotate_right(self, n)
+        }
+
+        #[inline]
+        fn swap_bytes(self) -> Self {
+            Self::swap_bytes(self)
+        }
+
+        #[inline]
+        fn reverse_bits(self) -> Self {
+            Self::reverse_bits(self)
+        }
+
+        #[inline]
+        fn from_be(x: Self) -> Self {
+            Self::from_be(x)
+        }
+
+        #[inline]
+        fn from_le(x: Self) -> Self {
+            Self::from_le(x)
+        }
+
+        #[inline]
+        fn to_be(self) -> Self {
+            Self::to_be(self)
+        }
+
+        #[inline]
+        fn to_le(self) -> Self {
+            Self::to_le(self)
+        }
+
+        #[inline]
+        fn checked_add(self, rhs: Self) -> Option<Self> {
+            Self::checked_add(self, rhs)
+        }
+
+        #[inline]
+        fn strict_add(self, rhs: Self) -> Self {
+            Self::strict_add(self, rhs)
+        }
+
+        #[inline]
+        unsafe fn unchecked_add(self, rhs: Self) -> Self {
+            // SAFETY: deferred to the caller
+            unsafe { Self::unchecked_add(self, rhs) }
+        }
+
+        #[inline]
+        fn checked_sub(self, rhs: Self) -> Option<Self> {
+            Self::checked_sub(self, rhs)
+        }
+
+        #[inline]
+        fn strict_sub(self, rhs: Self) -> Self {
+            Self::strict_sub(self, rhs)
+        }
+
+        #[inline]
+        unsafe fn unchecked_sub(self, rhs: Self) -> Self {
+            // SAFETY: deferred to the caller
+            unsafe { Self::unchecked_sub(self, rhs) }
+        }
+
+        #[inline]
+        fn checked_mul(self, rhs: Self) -> Option<Self> {
+            Self::checked_mul(self, rhs)
+        }
+
+        #[inline]
+        fn strict_mul(self, rhs: Self) -> Self {
+            Self::strict_mul(self, rhs)
+        }
+
+        #[inline]
+        unsafe fn unchecked_mul(self, rhs: Self) -> Self {
+            // SAFETY: deferred to the caller
+            unsafe { Self::unchecked_mul(self, rhs) }
+        }
+
+        #[inline]
+        fn checked_div(self, rhs: Self) -> Option<Self> {
+            Self::checked_div(self, rhs)
+        }
+
+        #[inline]
+        fn strict_div(self, rhs: Self) -> Self {
+            Self::strict_div(self, rhs)
+        }
+
+        #[inline]
+        fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
+            Self::checked_div_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn strict_div_euclid(self, rhs: Self) -> Self {
+            Self::strict_div_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn checked_rem(self, rhs: Self) -> Option<Self> {
+            Self::checked_rem(self, rhs)
+        }
+
+        #[inline]
+        fn strict_rem(self, rhs: Self) -> Self {
+            Self::strict_rem(self, rhs)
+        }
+
+        #[inline]
+        fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
+            Self::checked_rem_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn strict_rem_euclid(self, rhs: Self) -> Self {
+            Self::strict_rem_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn checked_neg(self) -> Option<Self> {
+            Self::checked_neg(self)
+        }
+
+        #[inline]
+        fn strict_neg(self) -> Self {
+            Self::strict_neg(self)
+        }
+
+        #[inline]
+        fn checked_shl(self, rhs: u32) -> Option<Self> {
+            Self::checked_shl(self, rhs)
+        }
+
+        #[inline]
+        fn strict_shl(self, rhs: u32) -> Self {
+            Self::strict_shl(self, rhs)
+        }
+
+        #[inline]
+        unsafe fn unchecked_shl(self, rhs: u32) -> Self {
+            // SAFETY: deferred to the caller
+            unsafe { Self::unchecked_shl(self, rhs) }
+        }
+
+        #[inline]
+        fn checked_shr(self, rhs: u32) -> Option<Self> {
+            Self::checked_shr(self, rhs)
+        }
+
+        #[inline]
+        fn strict_shr(self, rhs: u32) -> Self {
+            Self::strict_shr(self, rhs)
+        }
+
+        #[inline]
+        unsafe fn unchecked_shr(self, rhs: u32) -> Self {
+            // SAFETY: deferred to the caller
+            unsafe { Self::unchecked_shr(self, rhs) }
+        }
+
+        #[inline]
+        fn checked_pow(self, exp: u32) -> Option<Self> {
+            Self::checked_pow(self, exp)
+        }
+
+        #[inline]
+        fn strict_pow(self, exp: u32) -> Self {
+            Self::strict_pow(self, exp)
+        }
+
+        #[inline]
+        fn saturating_add(self, rhs: Self) -> Self {
+            Self::saturating_add(self, rhs)
+        }
+
+        #[inline]
+        fn saturating_sub(self, rhs: Self) -> Self {
+            Self::saturating_sub(self, rhs)
+        }
+
+        #[inline]
+        fn saturating_mul(self, rhs: Self) -> Self {
+            Self::saturating_mul(self, rhs)
+        }
+
+        #[inline]
+        fn saturating_div(self, rhs: Self) -> Self {
+            Self::saturating_div(self, rhs)
+        }
+
+        #[inline]
+        fn saturating_pow(self, exp: u32) -> Self {
+            Self::saturating_pow(self, exp)
+        }
+
+        #[inline]
+        fn wrapping_add(self, rhs: Self) -> Self {
+            Self::wrapping_add(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_sub(self, rhs: Self) -> Self {
+            Self::wrapping_sub(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_mul(self, rhs: Self) -> Self {
+            Self::wrapping_mul(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_div(self, rhs: Self) -> Self {
+            Self::wrapping_div(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_div_euclid(self, rhs: Self) -> Self {
+            Self::wrapping_div_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_rem(self, rhs: Self) -> Self {
+            Self::wrapping_rem(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_rem_euclid(self, rhs: Self) -> Self {
+            Self::wrapping_rem_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_neg(self) -> Self {
+            Self::wrapping_neg(self)
+        }
+
+        #[inline]
+        fn wrapping_shl(self, rhs: u32) -> Self {
+            Self::wrapping_shl(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_shr(self, rhs: u32) -> Self {
+            Self::wrapping_shr(self, rhs)
+        }
+
+        #[inline]
+        fn wrapping_pow(self, exp: u32) -> Self {
+            Self::wrapping_pow(self, exp)
+        }
+
+        #[inline]
+        fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_add(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_sub(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_mul(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_div(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_div_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_rem(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
+            Self::overflowing_rem_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_neg(self) -> (Self, bool) {
+            Self::overflowing_neg(self)
+        }
+
+        #[inline]
+        fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            Self::overflowing_shl(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            Self::overflowing_shr(self, rhs)
+        }
+
+        #[inline]
+        fn overflowing_pow(self, exp: u32) -> (Self, bool) {
+            Self::overflowing_pow(self, exp)
+        }
+
+        #[inline]
+        fn pow(self, exp: u32) -> Self {
+            Self::pow(self, exp)
+        }
+
+        #[inline]
+        fn isqrt(self) -> Self {
+            Self::isqrt(self)
+        }
+
+        #[inline]
+        fn div_euclid(self, rhs: Self) -> Self {
+            Self::div_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn rem_euclid(self, rhs: Self) -> Self {
+            Self::rem_euclid(self, rhs)
+        }
+
+        #[inline]
+        fn div_floor(self, rhs: Self) -> Self {
+            Self::div_floor(self, rhs)
+        }
+
+        #[inline]
+        fn div_ceil(self, rhs: Self) -> Self {
+            Self::div_ceil(self, rhs)
+        }
+
+        #[inline]
+        fn next_multiple_of(self, rhs: Self) -> Self {
+            Self::next_multiple_of(self, rhs)
+        }
+
+        #[inline]
+        fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
+            Self::checked_next_multiple_of(self, rhs)
+        }
+
+        #[inline]
+        #[allow(deprecated_in_future)]
+        fn min_value() -> Self {
+            Self::min_value()
+        }
+
+        #[inline]
+        #[allow(deprecated_in_future)]
+        fn max_value() -> Self {
+            Self::max_value()
+        }
+    };
+}
diff --git a/library/core/src/primitive/mod.rs b/library/core/src/primitive/mod.rs
new file mode 100644
index 0000000000000..509e4705c8fba
--- /dev/null
+++ b/library/core/src/primitive/mod.rs
@@ -0,0 +1,367 @@
+//! This module reexports the primitive types to allow usage that is not
+//! possibly shadowed by other declared types.
+//!
+//! This is normally only useful in macro generated code.
+//!
+//! An example of this is when generating a new struct and an impl for it:
+//!
+//! ```rust,compile_fail
+//! pub struct bool;
+//!
+//! impl QueryId for bool {
+//!     const SOME_PROPERTY: bool = true;
+//! }
+//!
+//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
+//! ```
+//!
+//! Note that the `SOME_PROPERTY` associated constant would not compile, as its
+//! type `bool` refers to the struct, rather than to the primitive bool type.
+//!
+//! A correct implementation could look like:
+//!
+//! ```rust
+//! # #[allow(non_camel_case_types)]
+//! pub struct bool;
+//!
+//! impl QueryId for bool {
+//!     const SOME_PROPERTY: core::primitive::bool = true;
+//! }
+//!
+//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
+//! ```
+
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use bool;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use char;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use f32;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use f64;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use i128;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use i16;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use i32;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use i64;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use i8;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use isize;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use str;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use u128;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use u16;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use u32;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use u64;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use u8;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use usize;
+
+mod sealed {
+    /// This trait being unreachable from outside the crate prevents downstream
+    /// implementations, permitting extension of the subtraits without breakage.
+    #[unstable(
+        feature = "primitive_abstraction_internals",
+        reason = "should be replaced by #[sealed] once available",
+        issue = "none"
+    )]
+    pub trait Sealed {}
+}
+
+#[macro_use]
+mod int_macros; // import int_decl!, int_impl!
+#[macro_use]
+mod float_macros; // import float_decl!, float_impl!
+
+use crate::{fmt, hash, iter, ops, panic};
+use sealed::Sealed;
+
+/// A trait implemented by all *primitive* integer types, signed or unsigned.
+///
+/// This trait is sealed and cannot be implemented for types outside of the
+/// standard library. It is not intended to be a general-purpose numerical
+/// abstraction. By being limited to primitive integers, this trait can add
+/// new functionality as it is provided without risk of breaking implementors.
+#[fundamental]
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+pub trait Integer:
+    'static + sealed::Sealed
+    // core::marker
+    + Sized + Copy + Clone + Send + Sync + Unpin
+    // core::panic
+    + panic::UnwindSafe + panic::RefUnwindSafe
+    // core::fmt
+    + fmt::Debug + fmt::Display + fmt::Binary + fmt::Octal
+    + fmt::LowerHex + fmt::UpperHex + fmt::LowerExp + fmt::UpperExp
+    // core::default
+    + Default
+    // core::cmp
+    + PartialEq + Eq + PartialOrd + Ord
+    // core::hash
+    + hash::Hash
+    // core::str
+    + crate::str::FromStr
+    // core::convert
+    + TryFrom<u8> + TryInto<u8>
+    + TryFrom<u16> + TryInto<u16>
+    + TryFrom<u32> + TryInto<u32>
+    + TryFrom<u64> + TryInto<u64>
+    + TryFrom<u128> + TryInto<u128>
+    + TryFrom<usize> + TryInto<usize>
+    + TryFrom<i8> + TryInto<i8>
+    + TryFrom<i16> + TryInto<i16>
+    + TryFrom<i32> + TryInto<i32>
+    + TryFrom<i64> + TryInto<i64>
+    + TryFrom<i128> + TryInto<i128>
+    + TryFrom<isize> + TryInto<isize>
+    // core::ops
+    + ops::Add<Output = Self> + for<'a> ops::Add<&'a Self, Output = Self>
+    + ops::Sub<Output = Self> + for<'a> ops::Sub<&'a Self, Output = Self>
+    + ops::Mul<Output = Self> + for<'a> ops::Mul<&'a Self, Output = Self>
+    + ops::Div<Output = Self> + for<'a> ops::Div<&'a Self, Output = Self>
+    + ops::Rem<Output = Self> + for<'a> ops::Rem<&'a Self, Output = Self>
+    + ops::AddAssign + for<'a> ops::AddAssign<&'a Self>
+    + ops::SubAssign + for<'a> ops::SubAssign<&'a Self>
+    + ops::MulAssign + for<'a> ops::MulAssign<&'a Self>
+    + ops::DivAssign + for<'a> ops::DivAssign<&'a Self>
+    + ops::RemAssign + for<'a> ops::RemAssign<&'a Self>
+    + ops::Not<Output = Self>
+    + ops::BitAnd<Output = Self> + for<'a> ops::BitAnd<&'a Self, Output = Self>
+    + ops::BitOr<Output = Self> + for<'a> ops::BitOr<&'a Self, Output = Self>
+    + ops::BitXor<Output = Self> + for<'a> ops::BitXor<&'a Self, Output = Self>
+    + ops::BitAndAssign + for<'a> ops::BitAndAssign<&'a Self>
+    + ops::BitOrAssign + for<'a> ops::BitOrAssign<&'a Self>
+    + ops::BitXorAssign + for<'a> ops::BitXorAssign<&'a Self>
+    + ops::Shl<u8, Output = Self> + for<'a> ops::Shl<&'a u8, Output = Self>
+    + ops::Shl<u16, Output = Self> + for<'a> ops::Shl<&'a u16, Output = Self>
+    + ops::Shl<u32, Output = Self> + for<'a> ops::Shl<&'a u32, Output = Self>
+    + ops::Shl<u64, Output = Self> + for<'a> ops::Shl<&'a u64, Output = Self>
+    + ops::Shl<u128, Output = Self> + for<'a> ops::Shl<&'a u128, Output = Self>
+    + ops::Shl<usize, Output = Self> + for<'a> ops::Shl<&'a usize, Output = Self>
+    + ops::Shl<i8, Output = Self> + for<'a> ops::Shl<&'a i8, Output = Self>
+    + ops::Shl<i16, Output = Self> + for<'a> ops::Shl<&'a i16, Output = Self>
+    + ops::Shl<i32, Output = Self> + for<'a> ops::Shl<&'a i32, Output = Self>
+    + ops::Shl<i64, Output = Self> + for<'a> ops::Shl<&'a i64, Output = Self>
+    + ops::Shl<i128, Output = Self> + for<'a> ops::Shl<&'a i128, Output = Self>
+    + ops::Shl<isize, Output = Self> + for<'a> ops::Shl<&'a isize, Output = Self>
+    + ops::Shl<Self, Output = Self> + for<'a> ops::Shl<&'a Self, Output = Self>
+    + ops::Shr<u8, Output = Self> + for<'a> ops::Shr<&'a u8, Output = Self>
+    + ops::Shr<u16, Output = Self> + for<'a> ops::Shr<&'a u16, Output = Self>
+    + ops::Shr<u32, Output = Self> + for<'a> ops::Shr<&'a u32, Output = Self>
+    + ops::Shr<u64, Output = Self> + for<'a> ops::Shr<&'a u64, Output = Self>
+    + ops::Shr<u128, Output = Self> + for<'a> ops::Shr<&'a u128, Output = Self>
+    + ops::Shr<usize, Output = Self> + for<'a> ops::Shr<&'a usize, Output = Self>
+    + ops::Shr<i8, Output = Self> + for<'a> ops::Shr<&'a i8, Output = Self>
+    + ops::Shr<i16, Output = Self> + for<'a> ops::Shr<&'a i16, Output = Self>
+    + ops::Shr<i32, Output = Self> + for<'a> ops::Shr<&'a i32, Output = Self>
+    + ops::Shr<i64, Output = Self> + for<'a> ops::Shr<&'a i64, Output = Self>
+    + ops::Shr<i128, Output = Self> + for<'a> ops::Shr<&'a i128, Output = Self>
+    + ops::Shr<isize, Output = Self> + for<'a> ops::Shr<&'a isize, Output = Self>
+    + ops::Shr<Self, Output = Self> + for<'a> ops::Shr<&'a Self, Output = Self>
+    + ops::ShlAssign<u8> + for<'a> ops::ShlAssign<&'a u8>
+    + ops::ShlAssign<u16> + for<'a> ops::ShlAssign<&'a u16>
+    + ops::ShlAssign<u32> + for<'a> ops::ShlAssign<&'a u32>
+    + ops::ShlAssign<u64> + for<'a> ops::ShlAssign<&'a u64>
+    + ops::ShlAssign<u128> + for<'a> ops::ShlAssign<&'a u128>
+    + ops::ShlAssign<usize> + for<'a> ops::ShlAssign<&'a usize>
+    + ops::ShlAssign<i8> + for<'a> ops::ShlAssign<&'a i8>
+    + ops::ShlAssign<i16> + for<'a> ops::ShlAssign<&'a i16>
+    + ops::ShlAssign<i32> + for<'a> ops::ShlAssign<&'a i32>
+    + ops::ShlAssign<i64> + for<'a> ops::ShlAssign<&'a i64>
+    + ops::ShlAssign<i128> + for<'a> ops::ShlAssign<&'a i128>
+    + ops::ShlAssign<isize> + for<'a> ops::ShlAssign<&'a isize>
+    + ops::ShlAssign<Self> + for<'a> ops::ShlAssign<&'a Self>
+    + ops::ShrAssign<u8> + for<'a> ops::ShrAssign<&'a u8>
+    + ops::ShrAssign<u16> + for<'a> ops::ShrAssign<&'a u16>
+    + ops::ShrAssign<u32> + for<'a> ops::ShrAssign<&'a u32>
+    + ops::ShrAssign<u64> + for<'a> ops::ShrAssign<&'a u64>
+    + ops::ShrAssign<u128> + for<'a> ops::ShrAssign<&'a u128>
+    + ops::ShrAssign<usize> + for<'a> ops::ShrAssign<&'a usize>
+    + ops::ShrAssign<i8> + for<'a> ops::ShrAssign<&'a i8>
+    + ops::ShrAssign<i16> + for<'a> ops::ShrAssign<&'a i16>
+    + ops::ShrAssign<i32> + for<'a> ops::ShrAssign<&'a i32>
+    + ops::ShrAssign<i64> + for<'a> ops::ShrAssign<&'a i64>
+    + ops::ShrAssign<i128> + for<'a> ops::ShrAssign<&'a i128>
+    + ops::ShrAssign<isize> + for<'a> ops::ShrAssign<&'a isize>
+    + ops::ShrAssign<Self> + for<'a> ops::ShrAssign<&'a Self>
+    // core::iter
+    + iter::Sum<Self> + for<'a> iter::Sum<&'a Self>
+    + iter::Product<Self> + for<'a> iter::Product<&'a Self>
+{
+    int_decl!();
+}
+
+/// A trait implemented by all *primitive* floating point types.
+///
+/// This trait is sealed and cannot be implemented for types outside of the
+/// standard library. It is not intended to be a general-purpose numerical
+/// abstraction. By being limited to primitive floating point, this trait can add
+/// new functionality as it is provided without risk of breaking implementors.
+#[fundamental]
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+pub trait Float:
+    'static + sealed::Sealed
+    // core::marker
+    + Sized + Copy + Clone + Send + Sync + Unpin
+    // core::panic
+    + panic::UnwindSafe + panic::RefUnwindSafe
+    // core::fmt
+    + fmt::Debug // + fmt::Display + fmt::LowerExp + fmt::UpperExp
+    // core::default
+    + Default
+    // core::cmp
+    + PartialEq + PartialOrd
+    // core::ops
+    + ops::Add<Output = Self> + for<'a> ops::Add<&'a Self, Output = Self>
+    + ops::Sub<Output = Self> + for<'a> ops::Sub<&'a Self, Output = Self>
+    + ops::Mul<Output = Self> + for<'a> ops::Mul<&'a Self, Output = Self>
+    + ops::Div<Output = Self> + for<'a> ops::Div<&'a Self, Output = Self>
+    + ops::Rem<Output = Self> + for<'a> ops::Rem<&'a Self, Output = Self>
+    + ops::AddAssign + for<'a> ops::AddAssign<&'a Self>
+    + ops::SubAssign + for<'a> ops::SubAssign<&'a Self>
+    + ops::MulAssign + for<'a> ops::MulAssign<&'a Self>
+    + ops::DivAssign + for<'a> ops::DivAssign<&'a Self>
+    + ops::RemAssign + for<'a> ops::RemAssign<&'a Self>
+    + ops::Neg
+{
+    float_decl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for u8 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for u8 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for u16 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for u16 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for u32 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for u32 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for u64 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for u64 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for u128 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for u128 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for usize {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for usize {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for i8 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for i8 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for i16 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for i16 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for i32 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for i32 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for i64 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for i64 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for i128 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for i128 {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for isize {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Integer for isize {
+    int_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for f16 {}
+
+#[cfg(not(bootstrap))]
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Float for f16 {
+    float_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for f32 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Float for f32 {
+    float_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for f64 {}
+
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Float for f64 {
+    float_impl!();
+}
+
+#[unstable(feature = "primitive_abstraction_internals", issue = "none")]
+impl Sealed for f128 {}
+
+#[cfg(not(bootstrap))]
+#[unstable(feature = "primitive_abstraction", issue = "none")]
+impl Float for f128 {
+    float_impl!();
+}
diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff
index 311de9e1c93f3..bf206c7129b9f 100644
--- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff
+++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff
@@ -70,8 +70,8 @@
       bb2: {
           _6 = Shl(move _7, const 1_i32);
           StorageDead(_7);
--         _3 = rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
-+         _3 = rotate_right::<u32>(_14, move _6) -> [return: bb3, unwind unreachable];
+-         _3 = std::intrinsics::rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
++         _3 = std::intrinsics::rotate_right::<u32>(_14, move _6) -> [return: bb3, unwind unreachable];
       }
   
       bb3: {
diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff
index c5fd042161d27..41c8940c67075 100644
--- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff
+++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff
@@ -70,8 +70,8 @@
       bb2: {
           _6 = Shl(move _7, const 1_i32);
           StorageDead(_7);
--         _3 = rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
-+         _3 = rotate_right::<u32>(_14, move _6) -> [return: bb3, unwind unreachable];
+-         _3 = std::intrinsics::rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
++         _3 = std::intrinsics::rotate_right::<u32>(_14, move _6) -> [return: bb3, unwind unreachable];
       }
   
       bb3: {
diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff
index 3c9694d0370d8..ad4f3bb5f9aaa 100644
--- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff
+++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff
@@ -67,7 +67,7 @@
           _5 = _1;
           StorageLive(_6);
           _6 = _2;
--         _4 = unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
+-         _4 = std::intrinsics::unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
 +         _4 = AddUnchecked(move _5, move _6);
 +         goto -> bb1;
       }
@@ -80,7 +80,7 @@
           _8 = _1;
           StorageLive(_9);
           _9 = _2;
--         _7 = unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
+-         _7 = std::intrinsics::unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
 +         _7 = SubUnchecked(move _8, move _9);
 +         goto -> bb2;
       }
@@ -93,7 +93,7 @@
           _11 = _1;
           StorageLive(_12);
           _12 = _2;
--         _10 = unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
+-         _10 = std::intrinsics::unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
 +         _10 = MulUnchecked(move _11, move _12);
 +         goto -> bb3;
       }
@@ -132,7 +132,7 @@
           _20 = _1;
           StorageLive(_21);
           _21 = _2;
--         _19 = unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
+-         _19 = std::intrinsics::unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
 +         _19 = ShlUnchecked(move _20, move _21);
 +         goto -> bb6;
       }
@@ -145,7 +145,7 @@
           _23 = _1;
           StorageLive(_24);
           _24 = _2;
--         _22 = unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
+-         _22 = std::intrinsics::unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
 +         _22 = ShrUnchecked(move _23, move _24);
 +         goto -> bb7;
       }
@@ -158,7 +158,7 @@
           _26 = _1;
           StorageLive(_27);
           _27 = _3;
--         _25 = unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
+-         _25 = std::intrinsics::unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
 +         _25 = ShlUnchecked(move _26, move _27);
 +         goto -> bb8;
       }
@@ -171,7 +171,7 @@
           _29 = _1;
           StorageLive(_30);
           _30 = _3;
--         _28 = unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
+-         _28 = std::intrinsics::unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
 +         _28 = ShrUnchecked(move _29, move _30);
 +         goto -> bb9;
       }
diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff
index 3c9694d0370d8..ad4f3bb5f9aaa 100644
--- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff
@@ -67,7 +67,7 @@
           _5 = _1;
           StorageLive(_6);
           _6 = _2;
--         _4 = unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
+-         _4 = std::intrinsics::unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
 +         _4 = AddUnchecked(move _5, move _6);
 +         goto -> bb1;
       }
@@ -80,7 +80,7 @@
           _8 = _1;
           StorageLive(_9);
           _9 = _2;
--         _7 = unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
+-         _7 = std::intrinsics::unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
 +         _7 = SubUnchecked(move _8, move _9);
 +         goto -> bb2;
       }
@@ -93,7 +93,7 @@
           _11 = _1;
           StorageLive(_12);
           _12 = _2;
--         _10 = unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
+-         _10 = std::intrinsics::unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
 +         _10 = MulUnchecked(move _11, move _12);
 +         goto -> bb3;
       }
@@ -132,7 +132,7 @@
           _20 = _1;
           StorageLive(_21);
           _21 = _2;
--         _19 = unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
+-         _19 = std::intrinsics::unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
 +         _19 = ShlUnchecked(move _20, move _21);
 +         goto -> bb6;
       }
@@ -145,7 +145,7 @@
           _23 = _1;
           StorageLive(_24);
           _24 = _2;
--         _22 = unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
+-         _22 = std::intrinsics::unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
 +         _22 = ShrUnchecked(move _23, move _24);
 +         goto -> bb7;
       }
@@ -158,7 +158,7 @@
           _26 = _1;
           StorageLive(_27);
           _27 = _3;
--         _25 = unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
+-         _25 = std::intrinsics::unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
 +         _25 = ShlUnchecked(move _26, move _27);
 +         goto -> bb8;
       }
@@ -171,7 +171,7 @@
           _29 = _1;
           StorageLive(_30);
           _30 = _3;
--         _28 = unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
+-         _28 = std::intrinsics::unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
 +         _28 = ShrUnchecked(move _29, move _30);
 +         goto -> bb9;
       }
diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff
index 2acb193e054d5..720fa0179e147 100644
--- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff
+++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff
@@ -56,7 +56,7 @@
           _10 = _1;
           StorageLive(_11);
           _11 = _2;
--         _9 = wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
+-         _9 = std::intrinsics::wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
 +         _9 = Mul(move _10, move _11);
 +         goto -> bb3;
       }
diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff
index 2acb193e054d5..720fa0179e147 100644
--- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff
@@ -56,7 +56,7 @@
           _10 = _1;
           StorageLive(_11);
           _11 = _2;
--         _9 = wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
+-         _9 = std::intrinsics::wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
 +         _9 = Mul(move _10, move _11);
 +         goto -> bb3;
       }
diff --git a/tests/ui/const-generics/wrong-normalization.stderr b/tests/ui/const-generics/wrong-normalization.stderr
index 379a5593dd640..0db15ba8fc98e 100644
--- a/tests/ui/const-generics/wrong-normalization.stderr
+++ b/tests/ui/const-generics/wrong-normalization.stderr
@@ -12,10 +12,15 @@ error[E0599]: no associated item named `MIN` found for type `i8` in the current
 LL | impl <I8<{i8::MIN}> as Identity>::Identity {
    |               ^^^ associated item not found in `i8`
    |
+   = help: items from traits can only be used if the trait is in scope
 help: you are looking for the module in `std`, not the primitive type
    |
 LL | impl <I8<{std::i8::MIN}> as Identity>::Identity {
    |           +++++
+help: trait `Integer` which provides `MIN` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use std::primitive::Integer;
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/intrinsics/unchecked_math_unsafe.stderr b/tests/ui/intrinsics/unchecked_math_unsafe.stderr
index 31da1a86ca135..bbb832610f78f 100644
--- a/tests/ui/intrinsics/unchecked_math_unsafe.stderr
+++ b/tests/ui/intrinsics/unchecked_math_unsafe.stderr
@@ -1,4 +1,4 @@
-error[E0133]: call to unsafe function `unchecked_add` is unsafe and requires unsafe function or block
+error[E0133]: call to unsafe function `std::intrinsics::unchecked_add` is unsafe and requires unsafe function or block
   --> $DIR/unchecked_math_unsafe.rs:5:15
    |
 LL |     let add = std::intrinsics::unchecked_add(x, y);
@@ -6,7 +6,7 @@ LL |     let add = std::intrinsics::unchecked_add(x, y);
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
-error[E0133]: call to unsafe function `unchecked_sub` is unsafe and requires unsafe function or block
+error[E0133]: call to unsafe function `std::intrinsics::unchecked_sub` is unsafe and requires unsafe function or block
   --> $DIR/unchecked_math_unsafe.rs:6:15
    |
 LL |     let sub = std::intrinsics::unchecked_sub(x, y);
@@ -14,7 +14,7 @@ LL |     let sub = std::intrinsics::unchecked_sub(x, y);
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
-error[E0133]: call to unsafe function `unchecked_mul` is unsafe and requires unsafe function or block
+error[E0133]: call to unsafe function `std::intrinsics::unchecked_mul` is unsafe and requires unsafe function or block
   --> $DIR/unchecked_math_unsafe.rs:7:15
    |
 LL |     let mul = std::intrinsics::unchecked_mul(x, y);