diff --git a/library/core/src/intrinsics/bounds.rs b/library/core/src/intrinsics/bounds.rs index 21705005ed0ae..377465aeb10fd 100644 --- a/library/core/src/intrinsics/bounds.rs +++ b/library/core/src/intrinsics/bounds.rs @@ -44,9 +44,68 @@ impl ChangePointee for *const T { /// /// # Safety /// Must actually *be* such a type. -pub unsafe trait FloatPrimitive: Sized + Copy {} +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] +pub const unsafe trait FloatPrimitive: Sized + Copy { + type UInt: const core::ops::BitOr + + const core::ops::BitAnd + + const core::ops::Not; + const SIGN_MASK: Self::UInt; + fn to_bits(self) -> Self::UInt; + fn from_bits(bits: Self::UInt) -> Self; +} + +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] +const unsafe impl FloatPrimitive for f16 { + type UInt = u16; + const SIGN_MASK: Self::UInt = f16::SIGN_MASK; + #[inline] + fn to_bits(self) -> Self::UInt { + f16::to_bits(self) + } + #[inline] + fn from_bits(bits: Self::UInt) -> Self { + f16::from_bits(bits) + } +} + +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] +const unsafe impl FloatPrimitive for f32 { + type UInt = u32; + const SIGN_MASK: Self::UInt = f32::SIGN_MASK; + #[inline] + fn to_bits(self) -> Self::UInt { + f32::to_bits(self) + } + #[inline] + fn from_bits(bits: Self::UInt) -> Self { + f32::from_bits(bits) + } +} + +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] +const unsafe impl FloatPrimitive for f64 { + type UInt = u64; + const SIGN_MASK: Self::UInt = f64::SIGN_MASK; + #[inline] + fn to_bits(self) -> Self::UInt { + f64::to_bits(self) + } + #[inline] + fn from_bits(bits: Self::UInt) -> Self { + f64::from_bits(bits) + } +} -unsafe impl FloatPrimitive for f16 {} -unsafe impl FloatPrimitive for f32 {} -unsafe impl FloatPrimitive for f64 {} -unsafe impl FloatPrimitive for f128 {} +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] +const unsafe impl FloatPrimitive for f128 { + type UInt = u128; + const SIGN_MASK: Self::UInt = f128::SIGN_MASK; + #[inline] + fn to_bits(self) -> Self::UInt { + f128::to_bits(self) + } + #[inline] + fn from_bits(bits: Self::UInt) -> Self { + f128::from_bits(bits) + } +} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index db825a1c970db..e9875f31fe784 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3628,9 +3628,13 @@ pub const fn maximumf128(x: f128, y: f128) -> f128 { /// The stabilized versions of this intrinsic are available on the float /// primitives via the `abs` method. For example, [`f32::abs`]. #[rustc_nounwind] +#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn fabs(x: T) -> T; +#[miri::intrinsic_fallback_is_spec] +pub const fn fabs(x: T) -> T { + T::from_bits(x.to_bits() & !T::SIGN_MASK) +} /// Copies the sign from `y` to `x` for `f16` values. ///