mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #130157 - eduardosm:stabilize-const_float_classify, r=RalfJung
Stabilize `const_float_classify` Tracking issue: https://github.com/rust-lang/rust/issues/72505 Also reverts https://github.com/rust-lang/rust/pull/114486 Closes https://github.com/rust-lang/rust/issues/72505 Stabilized const API: ```rust impl f32 { pub const fn is_nan(self) -> bool; pub const fn is_infinite(self) -> bool; pub const fn is_finite(self) -> bool; pub const fn is_subnormal(self) -> bool; pub const fn is_normal(self) -> bool; pub const fn classify(self) -> FpCategory; pub const fn is_sign_positive(self) -> bool; pub const fn is_sign_negative(self) -> bool; } impl f64 { pub const fn is_nan(self) -> bool; pub const fn is_infinite(self) -> bool; pub const fn is_finite(self) -> bool; pub const fn is_subnormal(self) -> bool; pub const fn is_normal(self) -> bool; pub const fn classify(self) -> FpCategory; pub const fn is_sign_positive(self) -> bool; pub const fn is_sign_negative(self) -> bool; } ``` cc `@rust-lang/wg-const-eval` `@rust-lang/libs-api`
This commit is contained in:
commit
14f303bc14
@ -1703,7 +1703,7 @@ pub(crate) enum InvalidNanComparisons {
|
|||||||
#[diag(lint_invalid_nan_comparisons_eq_ne)]
|
#[diag(lint_invalid_nan_comparisons_eq_ne)]
|
||||||
EqNe {
|
EqNe {
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
suggestion: Option<InvalidNanComparisonsSuggestion>,
|
suggestion: InvalidNanComparisonsSuggestion,
|
||||||
},
|
},
|
||||||
#[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
|
#[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
|
||||||
LtLeGtGe,
|
LtLeGtGe,
|
||||||
|
@ -209,36 +209,32 @@ fn lint_nan<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn eq_ne(
|
fn eq_ne(
|
||||||
cx: &LateContext<'_>,
|
|
||||||
e: &hir::Expr<'_>,
|
e: &hir::Expr<'_>,
|
||||||
l: &hir::Expr<'_>,
|
l: &hir::Expr<'_>,
|
||||||
r: &hir::Expr<'_>,
|
r: &hir::Expr<'_>,
|
||||||
f: impl FnOnce(Span, Span) -> InvalidNanComparisonsSuggestion,
|
f: impl FnOnce(Span, Span) -> InvalidNanComparisonsSuggestion,
|
||||||
) -> InvalidNanComparisons {
|
) -> InvalidNanComparisons {
|
||||||
// FIXME(#72505): This suggestion can be restored if `f{32,64}::is_nan` is made const.
|
let suggestion = if let Some(l_span) = l.span.find_ancestor_inside(e.span)
|
||||||
let suggestion = (!cx.tcx.hir().is_inside_const_context(e.hir_id)).then(|| {
|
|
||||||
if let Some(l_span) = l.span.find_ancestor_inside(e.span)
|
|
||||||
&& let Some(r_span) = r.span.find_ancestor_inside(e.span)
|
&& let Some(r_span) = r.span.find_ancestor_inside(e.span)
|
||||||
{
|
{
|
||||||
f(l_span, r_span)
|
f(l_span, r_span)
|
||||||
} else {
|
} else {
|
||||||
InvalidNanComparisonsSuggestion::Spanless
|
InvalidNanComparisonsSuggestion::Spanless
|
||||||
}
|
};
|
||||||
});
|
|
||||||
|
|
||||||
InvalidNanComparisons::EqNe { suggestion }
|
InvalidNanComparisons::EqNe { suggestion }
|
||||||
}
|
}
|
||||||
|
|
||||||
let lint = match binop.node {
|
let lint = match binop.node {
|
||||||
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => {
|
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => {
|
||||||
eq_ne(cx, e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
|
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
|
||||||
nan_plus_binop: l_span.until(r_span),
|
nan_plus_binop: l_span.until(r_span),
|
||||||
float: r_span.shrink_to_hi(),
|
float: r_span.shrink_to_hi(),
|
||||||
neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()),
|
neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => {
|
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => {
|
||||||
eq_ne(cx, e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
|
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
|
||||||
nan_plus_binop: l_span.shrink_to_hi().to(r_span),
|
nan_plus_binop: l_span.shrink_to_hi().to(r_span),
|
||||||
float: l_span.shrink_to_hi(),
|
float: l_span.shrink_to_hi(),
|
||||||
neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()),
|
neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()),
|
||||||
|
@ -122,7 +122,6 @@
|
|||||||
#![feature(const_char_encode_utf8)]
|
#![feature(const_char_encode_utf8)]
|
||||||
#![feature(const_eval_select)]
|
#![feature(const_eval_select)]
|
||||||
#![feature(const_exact_div)]
|
#![feature(const_exact_div)]
|
||||||
#![feature(const_float_classify)]
|
|
||||||
#![feature(const_fmt_arguments_new)]
|
#![feature(const_fmt_arguments_new)]
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
|
@ -288,7 +288,7 @@ impl f128 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub(crate) const fn abs_private(self) -> f128 {
|
pub(crate) const fn abs_private(self) -> f128 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -319,7 +319,7 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
(self == f128::INFINITY) | (self == f128::NEG_INFINITY)
|
(self == f128::INFINITY) | (self == f128::NEG_INFINITY)
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
// the comparison is not true, exactly as desired.
|
// the comparison is not true, exactly as desired.
|
||||||
@ -380,7 +380,7 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
}
|
}
|
||||||
@ -437,7 +437,7 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let bits = self.to_bits();
|
let bits = self.to_bits();
|
||||||
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
||||||
|
@ -282,7 +282,7 @@ impl f16 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub(crate) const fn abs_private(self) -> f16 {
|
pub(crate) const fn abs_private(self) -> f16 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
|
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
|
||||||
@ -310,7 +310,7 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
(self == f16::INFINITY) | (self == f16::NEG_INFINITY)
|
(self == f16::INFINITY) | (self == f16::NEG_INFINITY)
|
||||||
}
|
}
|
||||||
@ -336,7 +336,7 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
// the comparison is not true, exactly as desired.
|
// the comparison is not true, exactly as desired.
|
||||||
@ -368,7 +368,7 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
}
|
}
|
||||||
@ -398,7 +398,7 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
}
|
}
|
||||||
@ -422,7 +422,7 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let b = self.to_bits();
|
let b = self.to_bits();
|
||||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||||
|
@ -517,7 +517,7 @@ impl f32 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
|
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
|
||||||
pub const fn is_nan(self) -> bool {
|
pub const fn is_nan(self) -> bool {
|
||||||
@ -528,7 +528,6 @@ impl f32 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
|
||||||
pub(crate) const fn abs_private(self) -> f32 {
|
pub(crate) const fn abs_private(self) -> f32 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
|
unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
|
||||||
@ -551,7 +550,7 @@ impl f32 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
// Getting clever with transmutation can result in incorrect answers on some FPUs
|
// Getting clever with transmutation can result in incorrect answers on some FPUs
|
||||||
@ -576,7 +575,7 @@ impl f32 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
@ -604,7 +603,7 @@ impl f32 {
|
|||||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "is_subnormal", since = "1.53.0")]
|
#[stable(feature = "is_subnormal", since = "1.53.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
@ -631,7 +630,7 @@ impl f32 {
|
|||||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
@ -651,7 +650,7 @@ impl f32 {
|
|||||||
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||||
// around buggy codegen for x87 targets (see
|
// around buggy codegen for x87 targets (see
|
||||||
@ -687,7 +686,7 @@ impl f32 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_sign_positive(self) -> bool {
|
pub const fn is_sign_positive(self) -> bool {
|
||||||
!self.is_sign_negative()
|
!self.is_sign_negative()
|
||||||
@ -712,7 +711,7 @@ impl f32 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_sign_negative(self) -> bool {
|
pub const fn is_sign_negative(self) -> bool {
|
||||||
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
||||||
|
@ -516,7 +516,7 @@ impl f64 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
|
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
|
||||||
pub const fn is_nan(self) -> bool {
|
pub const fn is_nan(self) -> bool {
|
||||||
@ -527,7 +527,6 @@ impl f64 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
|
||||||
pub(crate) const fn abs_private(self) -> f64 {
|
pub(crate) const fn abs_private(self) -> f64 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
|
unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
|
||||||
@ -550,7 +549,7 @@ impl f64 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
// Getting clever with transmutation can result in incorrect answers on some FPUs
|
// Getting clever with transmutation can result in incorrect answers on some FPUs
|
||||||
@ -575,7 +574,7 @@ impl f64 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
@ -603,7 +602,7 @@ impl f64 {
|
|||||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "is_subnormal", since = "1.53.0")]
|
#[stable(feature = "is_subnormal", since = "1.53.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
@ -630,7 +629,7 @@ impl f64 {
|
|||||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
@ -650,7 +649,7 @@ impl f64 {
|
|||||||
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||||
// around buggy codegen for x87 targets (see
|
// around buggy codegen for x87 targets (see
|
||||||
@ -686,7 +685,7 @@ impl f64 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_sign_positive(self) -> bool {
|
pub const fn is_sign_positive(self) -> bool {
|
||||||
!self.is_sign_negative()
|
!self.is_sign_negative()
|
||||||
@ -720,7 +719,7 @@ impl f64 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_sign_negative(self) -> bool {
|
pub const fn is_sign_negative(self) -> bool {
|
||||||
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#![feature(f16_const)]
|
#![feature(f16_const)]
|
||||||
#![feature(f128_const)]
|
#![feature(f128_const)]
|
||||||
#![feature(const_float_classify)]
|
|
||||||
|
|
||||||
use std::num::FpCategory::*;
|
use std::num::FpCategory::*;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
// This tests the float classification functions, for regular runtime code and for const evaluation.
|
// This tests the float classification functions, for regular runtime code and for const evaluation.
|
||||||
|
|
||||||
#![feature(const_float_classify)]
|
|
||||||
#![feature(f16)]
|
#![feature(f16)]
|
||||||
#![feature(f128)]
|
#![feature(f128)]
|
||||||
#![feature(f16_const)]
|
#![feature(f16_const)]
|
||||||
|
@ -5,6 +5,11 @@ LL | const TEST: bool = 5f32 == f32::NAN;
|
|||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(invalid_nan_comparisons)]` on by default
|
= note: `#[warn(invalid_nan_comparisons)]` on by default
|
||||||
|
help: use `f32::is_nan()` or `f64::is_nan()` instead
|
||||||
|
|
|
||||||
|
LL - const TEST: bool = 5f32 == f32::NAN;
|
||||||
|
LL + const TEST: bool = 5f32.is_nan();
|
||||||
|
|
|
||||||
|
|
||||||
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
|
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
|
||||||
--> $DIR/invalid-nan-comparison.rs:14:5
|
--> $DIR/invalid-nan-comparison.rs:14:5
|
||||||
|
Loading…
Reference in New Issue
Block a user