Skip to content

Commit 14f303b

Browse files
committed
Auto merge of #130157 - eduardosm:stabilize-const_float_classify, r=RalfJung
Stabilize `const_float_classify` Tracking issue: #72505 Also reverts #114486 Closes #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`
2 parents c39f318 + c39ae56 commit 14f303b

File tree

10 files changed

+43
-47
lines changed

10 files changed

+43
-47
lines changed

compiler/rustc_lint/src/lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1703,7 +1703,7 @@ pub(crate) enum InvalidNanComparisons {
17031703
#[diag(lint_invalid_nan_comparisons_eq_ne)]
17041704
EqNe {
17051705
#[subdiagnostic]
1706-
suggestion: Option<InvalidNanComparisonsSuggestion>,
1706+
suggestion: InvalidNanComparisonsSuggestion,
17071707
},
17081708
#[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
17091709
LtLeGtGe,

compiler/rustc_lint/src/types.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -209,36 +209,32 @@ fn lint_nan<'tcx>(
209209
}
210210

211211
fn eq_ne(
212-
cx: &LateContext<'_>,
213212
e: &hir::Expr<'_>,
214213
l: &hir::Expr<'_>,
215214
r: &hir::Expr<'_>,
216215
f: impl FnOnce(Span, Span) -> InvalidNanComparisonsSuggestion,
217216
) -> InvalidNanComparisons {
218-
// FIXME(#72505): This suggestion can be restored if `f{32,64}::is_nan` is made const.
219-
let suggestion = (!cx.tcx.hir().is_inside_const_context(e.hir_id)).then(|| {
220-
if let Some(l_span) = l.span.find_ancestor_inside(e.span)
221-
&& let Some(r_span) = r.span.find_ancestor_inside(e.span)
222-
{
223-
f(l_span, r_span)
224-
} else {
225-
InvalidNanComparisonsSuggestion::Spanless
226-
}
227-
});
217+
let suggestion = if let Some(l_span) = l.span.find_ancestor_inside(e.span)
218+
&& let Some(r_span) = r.span.find_ancestor_inside(e.span)
219+
{
220+
f(l_span, r_span)
221+
} else {
222+
InvalidNanComparisonsSuggestion::Spanless
223+
};
228224

229225
InvalidNanComparisons::EqNe { suggestion }
230226
}
231227

232228
let lint = match binop.node {
233229
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => {
234-
eq_ne(cx, e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
230+
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
235231
nan_plus_binop: l_span.until(r_span),
236232
float: r_span.shrink_to_hi(),
237233
neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()),
238234
})
239235
}
240236
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => {
241-
eq_ne(cx, e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
237+
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
242238
nan_plus_binop: l_span.shrink_to_hi().to(r_span),
243239
float: l_span.shrink_to_hi(),
244240
neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()),

library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@
122122
#![feature(const_char_encode_utf8)]
123123
#![feature(const_eval_select)]
124124
#![feature(const_exact_div)]
125-
#![feature(const_float_classify)]
126125
#![feature(const_fmt_arguments_new)]
127126
#![feature(const_hash)]
128127
#![feature(const_heap)]

library/core/src/num/f128.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl f128 {
288288
// concerns about portability, so this implementation is for
289289
// private use internally.
290290
#[inline]
291-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
291+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
292292
pub(crate) const fn abs_private(self) -> f128 {
293293
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
294294
unsafe {
@@ -319,7 +319,7 @@ impl f128 {
319319
#[inline]
320320
#[must_use]
321321
#[unstable(feature = "f128", issue = "116909")]
322-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
322+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
323323
pub const fn is_infinite(self) -> bool {
324324
(self == f128::INFINITY) | (self == f128::NEG_INFINITY)
325325
}
@@ -346,7 +346,7 @@ impl f128 {
346346
#[inline]
347347
#[must_use]
348348
#[unstable(feature = "f128", issue = "116909")]
349-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
349+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
350350
pub const fn is_finite(self) -> bool {
351351
// There's no need to handle NaN separately: if self is NaN,
352352
// the comparison is not true, exactly as desired.
@@ -380,7 +380,7 @@ impl f128 {
380380
#[inline]
381381
#[must_use]
382382
#[unstable(feature = "f128", issue = "116909")]
383-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
383+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
384384
pub const fn is_subnormal(self) -> bool {
385385
matches!(self.classify(), FpCategory::Subnormal)
386386
}
@@ -412,7 +412,7 @@ impl f128 {
412412
#[inline]
413413
#[must_use]
414414
#[unstable(feature = "f128", issue = "116909")]
415-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
415+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
416416
pub const fn is_normal(self) -> bool {
417417
matches!(self.classify(), FpCategory::Normal)
418418
}
@@ -437,7 +437,7 @@ impl f128 {
437437
/// ```
438438
#[inline]
439439
#[unstable(feature = "f128", issue = "116909")]
440-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
440+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
441441
pub const fn classify(self) -> FpCategory {
442442
let bits = self.to_bits();
443443
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {

library/core/src/num/f16.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ impl f16 {
282282
// concerns about portability, so this implementation is for
283283
// private use internally.
284284
#[inline]
285-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
285+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
286286
pub(crate) const fn abs_private(self) -> f16 {
287287
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
288288
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
@@ -310,7 +310,7 @@ impl f16 {
310310
#[inline]
311311
#[must_use]
312312
#[unstable(feature = "f16", issue = "116909")]
313-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
313+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
314314
pub const fn is_infinite(self) -> bool {
315315
(self == f16::INFINITY) | (self == f16::NEG_INFINITY)
316316
}
@@ -336,7 +336,7 @@ impl f16 {
336336
#[inline]
337337
#[must_use]
338338
#[unstable(feature = "f16", issue = "116909")]
339-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
339+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
340340
pub const fn is_finite(self) -> bool {
341341
// There's no need to handle NaN separately: if self is NaN,
342342
// the comparison is not true, exactly as desired.
@@ -368,7 +368,7 @@ impl f16 {
368368
#[inline]
369369
#[must_use]
370370
#[unstable(feature = "f16", issue = "116909")]
371-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
371+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
372372
pub const fn is_subnormal(self) -> bool {
373373
matches!(self.classify(), FpCategory::Subnormal)
374374
}
@@ -398,7 +398,7 @@ impl f16 {
398398
#[inline]
399399
#[must_use]
400400
#[unstable(feature = "f16", issue = "116909")]
401-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
401+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
402402
pub const fn is_normal(self) -> bool {
403403
matches!(self.classify(), FpCategory::Normal)
404404
}
@@ -422,7 +422,7 @@ impl f16 {
422422
/// ```
423423
#[inline]
424424
#[unstable(feature = "f16", issue = "116909")]
425-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
425+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
426426
pub const fn classify(self) -> FpCategory {
427427
let b = self.to_bits();
428428
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {

library/core/src/num/f32.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ impl f32 {
517517
/// ```
518518
#[must_use]
519519
#[stable(feature = "rust1", since = "1.0.0")]
520-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
520+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
521521
#[inline]
522522
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
523523
pub const fn is_nan(self) -> bool {
@@ -528,7 +528,6 @@ impl f32 {
528528
// concerns about portability, so this implementation is for
529529
// private use internally.
530530
#[inline]
531-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
532531
pub(crate) const fn abs_private(self) -> f32 {
533532
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
534533
unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
@@ -551,7 +550,7 @@ impl f32 {
551550
/// ```
552551
#[must_use]
553552
#[stable(feature = "rust1", since = "1.0.0")]
554-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
553+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
555554
#[inline]
556555
pub const fn is_infinite(self) -> bool {
557556
// Getting clever with transmutation can result in incorrect answers on some FPUs
@@ -576,7 +575,7 @@ impl f32 {
576575
/// ```
577576
#[must_use]
578577
#[stable(feature = "rust1", since = "1.0.0")]
579-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
578+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
580579
#[inline]
581580
pub const fn is_finite(self) -> bool {
582581
// There's no need to handle NaN separately: if self is NaN,
@@ -604,7 +603,7 @@ impl f32 {
604603
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
605604
#[must_use]
606605
#[stable(feature = "is_subnormal", since = "1.53.0")]
607-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
606+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
608607
#[inline]
609608
pub const fn is_subnormal(self) -> bool {
610609
matches!(self.classify(), FpCategory::Subnormal)
@@ -631,7 +630,7 @@ impl f32 {
631630
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
632631
#[must_use]
633632
#[stable(feature = "rust1", since = "1.0.0")]
634-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
633+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
635634
#[inline]
636635
pub const fn is_normal(self) -> bool {
637636
matches!(self.classify(), FpCategory::Normal)
@@ -651,7 +650,7 @@ impl f32 {
651650
/// assert_eq!(inf.classify(), FpCategory::Infinite);
652651
/// ```
653652
#[stable(feature = "rust1", since = "1.0.0")]
654-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
653+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
655654
pub const fn classify(self) -> FpCategory {
656655
// We used to have complicated logic here that avoids the simple bit-based tests to work
657656
// around buggy codegen for x87 targets (see
@@ -687,7 +686,7 @@ impl f32 {
687686
/// ```
688687
#[must_use]
689688
#[stable(feature = "rust1", since = "1.0.0")]
690-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
689+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
691690
#[inline]
692691
pub const fn is_sign_positive(self) -> bool {
693692
!self.is_sign_negative()
@@ -712,7 +711,7 @@ impl f32 {
712711
/// ```
713712
#[must_use]
714713
#[stable(feature = "rust1", since = "1.0.0")]
715-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
714+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
716715
#[inline]
717716
pub const fn is_sign_negative(self) -> bool {
718717
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus

library/core/src/num/f64.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ impl f64 {
516516
/// ```
517517
#[must_use]
518518
#[stable(feature = "rust1", since = "1.0.0")]
519-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
519+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
520520
#[inline]
521521
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
522522
pub const fn is_nan(self) -> bool {
@@ -527,7 +527,6 @@ impl f64 {
527527
// concerns about portability, so this implementation is for
528528
// private use internally.
529529
#[inline]
530-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
531530
pub(crate) const fn abs_private(self) -> f64 {
532531
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
533532
unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
@@ -550,7 +549,7 @@ impl f64 {
550549
/// ```
551550
#[must_use]
552551
#[stable(feature = "rust1", since = "1.0.0")]
553-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
552+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
554553
#[inline]
555554
pub const fn is_infinite(self) -> bool {
556555
// Getting clever with transmutation can result in incorrect answers on some FPUs
@@ -575,7 +574,7 @@ impl f64 {
575574
/// ```
576575
#[must_use]
577576
#[stable(feature = "rust1", since = "1.0.0")]
578-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
577+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
579578
#[inline]
580579
pub const fn is_finite(self) -> bool {
581580
// There's no need to handle NaN separately: if self is NaN,
@@ -603,7 +602,7 @@ impl f64 {
603602
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
604603
#[must_use]
605604
#[stable(feature = "is_subnormal", since = "1.53.0")]
606-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
605+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
607606
#[inline]
608607
pub const fn is_subnormal(self) -> bool {
609608
matches!(self.classify(), FpCategory::Subnormal)
@@ -630,7 +629,7 @@ impl f64 {
630629
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
631630
#[must_use]
632631
#[stable(feature = "rust1", since = "1.0.0")]
633-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
632+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
634633
#[inline]
635634
pub const fn is_normal(self) -> bool {
636635
matches!(self.classify(), FpCategory::Normal)
@@ -650,7 +649,7 @@ impl f64 {
650649
/// assert_eq!(inf.classify(), FpCategory::Infinite);
651650
/// ```
652651
#[stable(feature = "rust1", since = "1.0.0")]
653-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
652+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
654653
pub const fn classify(self) -> FpCategory {
655654
// We used to have complicated logic here that avoids the simple bit-based tests to work
656655
// around buggy codegen for x87 targets (see
@@ -686,7 +685,7 @@ impl f64 {
686685
/// ```
687686
#[must_use]
688687
#[stable(feature = "rust1", since = "1.0.0")]
689-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
688+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
690689
#[inline]
691690
pub const fn is_sign_positive(self) -> bool {
692691
!self.is_sign_negative()
@@ -720,7 +719,7 @@ impl f64 {
720719
/// ```
721720
#[must_use]
722721
#[stable(feature = "rust1", since = "1.0.0")]
723-
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
722+
#[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")]
724723
#[inline]
725724
pub const fn is_sign_negative(self) -> bool {
726725
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus

tests/ui/float/classify-runtime-const.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#![feature(f16_const)]
1010
#![feature(f128_const)]
11-
#![feature(const_float_classify)]
1211

1312
use std::num::FpCategory::*;
1413

tests/ui/float/conv-bits-runtime-const.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
// This tests the float classification functions, for regular runtime code and for const evaluation.
55

6-
#![feature(const_float_classify)]
76
#![feature(f16)]
87
#![feature(f128)]
98
#![feature(f16_const)]

tests/ui/lint/invalid-nan-comparison.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | const TEST: bool = 5f32 == f32::NAN;
55
| ^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(invalid_nan_comparisons)]` on by default
8+
help: use `f32::is_nan()` or `f64::is_nan()` instead
9+
|
10+
LL - const TEST: bool = 5f32 == f32::NAN;
11+
LL + const TEST: bool = 5f32.is_nan();
12+
|
813

914
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
1015
--> $DIR/invalid-nan-comparison.rs:14:5

0 commit comments

Comments
 (0)