Skip to content

Commit 788c98d

Browse files
committedJun 10, 2023
Auto merge of rust-lang#111818 - Urgau:uplift_cmp_nan, r=cjgillot
Uplift `clippy::cmp_nan` lint This PR aims at uplifting the `clippy::cmp_nan` lint into rustc. ## `invalid_nan_comparisons` ~~(deny-by-default)~~ (warn-by-default) The `invalid_nan_comparisons` lint checks comparison with `f32::NAN` or `f64::NAN` as one of the operand. ### Example ```rust,compile_fail let a = 2.3f32; if a == f32::NAN {} ``` ### Explanation NaN does not compare meaningfully to anything – not even itself – so those comparisons are always false. ----- Mostly followed the instructions for uplifting a clippy lint described here: rust-lang#99696 (review) `@rustbot` label: +I-lang-nominated r? compiler
2 parents 4b71d79 + a814537 commit 788c98d

25 files changed

+604
-308
lines changed
 

‎compiler/rustc_lint/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal alw
314314
lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
315315
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
316316
317+
lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be directly compared to itself
318+
.suggestion = use `f32::is_nan()` or `f64::is_nan()` instead
319+
320+
lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
321+
317322
lint_lintpass_by_hand = implementing `LintPass` by hand
318323
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
319324

‎compiler/rustc_lint/src/lints.rs

+30
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,36 @@ pub struct OverflowingLiteral<'a> {
14341434
#[diag(lint_unused_comparisons)]
14351435
pub struct UnusedComparisons;
14361436

1437+
#[derive(LintDiagnostic)]
1438+
pub enum InvalidNanComparisons {
1439+
#[diag(lint_invalid_nan_comparisons_eq_ne)]
1440+
EqNe {
1441+
#[subdiagnostic]
1442+
suggestion: InvalidNanComparisonsSuggestion,
1443+
},
1444+
#[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
1445+
LtLeGtGe,
1446+
}
1447+
1448+
#[derive(Subdiagnostic)]
1449+
pub enum InvalidNanComparisonsSuggestion {
1450+
#[multipart_suggestion(
1451+
lint_suggestion,
1452+
style = "verbose",
1453+
applicability = "machine-applicable"
1454+
)]
1455+
Spanful {
1456+
#[suggestion_part(code = "!")]
1457+
neg: Option<Span>,
1458+
#[suggestion_part(code = ".is_nan()")]
1459+
float: Span,
1460+
#[suggestion_part(code = "")]
1461+
nan_plus_binop: Span,
1462+
},
1463+
#[help(lint_suggestion)]
1464+
Spanless,
1465+
}
1466+
14371467
pub struct ImproperCTypes<'a> {
14381468
pub ty: Ty<'a>,
14391469
pub desc: &'a str,

‎compiler/rustc_lint/src/types.rs

+95-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use crate::{
22
fluent_generated as fluent,
33
lints::{
44
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
5-
InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
6-
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
7-
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
8-
VariantSizeDifferencesDiag,
5+
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
6+
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
7+
OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
8+
RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
99
},
1010
};
1111
use crate::{LateContext, LateLintPass, LintContext};
@@ -113,13 +113,35 @@ declare_lint! {
113113
"detects enums with widely varying variant sizes"
114114
}
115115

116+
declare_lint! {
117+
/// The `invalid_nan_comparisons` lint checks comparison with `f32::NAN` or `f64::NAN`
118+
/// as one of the operand.
119+
///
120+
/// ### Example
121+
///
122+
/// ```rust
123+
/// let a = 2.3f32;
124+
/// if a == f32::NAN {}
125+
/// ```
126+
///
127+
/// {{produces}}
128+
///
129+
/// ### Explanation
130+
///
131+
/// NaN does not compare meaningfully to anything – not
132+
/// even itself – so those comparisons are always false.
133+
INVALID_NAN_COMPARISONS,
134+
Warn,
135+
"detects invalid floating point NaN comparisons"
136+
}
137+
116138
#[derive(Copy, Clone)]
117139
pub struct TypeLimits {
118140
/// Id of the last visited negated expression
119141
negated_expr_id: Option<hir::HirId>,
120142
}
121143

122-
impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS]);
144+
impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS, INVALID_NAN_COMPARISONS]);
123145

124146
impl TypeLimits {
125147
pub fn new() -> TypeLimits {
@@ -486,6 +508,68 @@ fn lint_literal<'tcx>(
486508
}
487509
}
488510

511+
fn lint_nan<'tcx>(
512+
cx: &LateContext<'tcx>,
513+
e: &'tcx hir::Expr<'tcx>,
514+
binop: hir::BinOp,
515+
l: &'tcx hir::Expr<'tcx>,
516+
r: &'tcx hir::Expr<'tcx>,
517+
) {
518+
fn is_nan(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
519+
let expr = expr.peel_blocks().peel_borrows();
520+
match expr.kind {
521+
ExprKind::Path(qpath) => {
522+
let Some(def_id) = cx.typeck_results().qpath_res(&qpath, expr.hir_id).opt_def_id() else { return false; };
523+
524+
matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::f32_nan | sym::f64_nan))
525+
}
526+
_ => false,
527+
}
528+
}
529+
530+
fn eq_ne(
531+
e: &hir::Expr<'_>,
532+
l: &hir::Expr<'_>,
533+
r: &hir::Expr<'_>,
534+
f: impl FnOnce(Span, Span) -> InvalidNanComparisonsSuggestion,
535+
) -> InvalidNanComparisons {
536+
let suggestion =
537+
if let Some(l_span) = l.span.find_ancestor_inside(e.span) &&
538+
let Some(r_span) = r.span.find_ancestor_inside(e.span) {
539+
f(l_span, r_span)
540+
} else {
541+
InvalidNanComparisonsSuggestion::Spanless
542+
};
543+
544+
InvalidNanComparisons::EqNe { suggestion }
545+
}
546+
547+
let lint = match binop.node {
548+
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => {
549+
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
550+
nan_plus_binop: l_span.until(r_span),
551+
float: r_span.shrink_to_hi(),
552+
neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()),
553+
})
554+
}
555+
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => {
556+
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
557+
nan_plus_binop: l_span.shrink_to_hi().to(r_span),
558+
float: l_span.shrink_to_hi(),
559+
neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()),
560+
})
561+
}
562+
hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Gt | hir::BinOpKind::Ge
563+
if is_nan(cx, l) || is_nan(cx, r) =>
564+
{
565+
InvalidNanComparisons::LtLeGtGe
566+
}
567+
_ => return,
568+
};
569+
570+
cx.emit_spanned_lint(INVALID_NAN_COMPARISONS, e.span, lint);
571+
}
572+
489573
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
490574
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
491575
match e.kind {
@@ -496,8 +580,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
496580
}
497581
}
498582
hir::ExprKind::Binary(binop, ref l, ref r) => {
499-
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
500-
cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
583+
if is_comparison(binop) {
584+
if !check_limits(cx, binop, &l, &r) {
585+
cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
586+
} else {
587+
lint_nan(cx, e, binop, l, r);
588+
}
501589
}
502590
}
503591
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),

‎compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,9 @@ symbols! {
701701
f,
702702
f16c_target_feature,
703703
f32,
704+
f32_nan,
704705
f64,
706+
f64_nan,
705707
fabsf32,
706708
fabsf64,
707709
fadd_fast,

‎library/core/src/num/f32.rs

+1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ impl f32 {
403403
/// and the stability of its representation over Rust versions
404404
/// and target platforms isn't guaranteed.
405405
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
406+
#[rustc_diagnostic_item = "f32_nan"]
406407
pub const NAN: f32 = 0.0_f32 / 0.0_f32;
407408
/// Infinity (∞).
408409
#[stable(feature = "assoc_int_consts", since = "1.43.0")]

‎library/core/src/num/f64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ impl f64 {
401401
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
402402
/// and the stability of its representation over Rust versions
403403
/// and target platforms isn't guaranteed.
404+
#[rustc_diagnostic_item = "f64_nan"]
404405
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
405406
pub const NAN: f64 = 0.0_f64 / 0.0_f64;
406407
/// Infinity (∞).

‎src/tools/clippy/clippy_lints/src/declared_lints.rs

-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
476476
crate::operators::ARITHMETIC_SIDE_EFFECTS_INFO,
477477
crate::operators::ASSIGN_OP_PATTERN_INFO,
478478
crate::operators::BAD_BIT_MASK_INFO,
479-
crate::operators::CMP_NAN_INFO,
480479
crate::operators::CMP_OWNED_INFO,
481480
crate::operators::DOUBLE_COMPARISONS_INFO,
482481
crate::operators::DURATION_SUBSEC_INFO,

‎src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs

-30
This file was deleted.

‎src/tools/clippy/clippy_lints/src/operators/mod.rs

-28
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
mod absurd_extreme_comparisons;
22
mod assign_op_pattern;
33
mod bit_mask;
4-
mod cmp_nan;
54
mod cmp_owned;
65
mod double_comparison;
76
mod duration_subsec;
@@ -485,31 +484,6 @@ declare_clippy_lint! {
485484
"integer division may cause loss of precision"
486485
}
487486

488-
declare_clippy_lint! {
489-
/// ### What it does
490-
/// Checks for comparisons to NaN.
491-
///
492-
/// ### Why is this bad?
493-
/// NaN does not compare meaningfully to anything – not
494-
/// even itself – so those comparisons are simply wrong.
495-
///
496-
/// ### Example
497-
/// ```rust
498-
/// # let x = 1.0;
499-
/// if x == f32::NAN { }
500-
/// ```
501-
///
502-
/// Use instead:
503-
/// ```rust
504-
/// # let x = 1.0f32;
505-
/// if x.is_nan() { }
506-
/// ```
507-
#[clippy::version = "pre 1.29.0"]
508-
pub CMP_NAN,
509-
correctness,
510-
"comparisons to `NAN`, which will always return false, probably not intended"
511-
}
512-
513487
declare_clippy_lint! {
514488
/// ### What it does
515489
/// Checks for conversions to owned values just for the sake
@@ -775,7 +749,6 @@ impl_lint_pass!(Operators => [
775749
FLOAT_EQUALITY_WITHOUT_ABS,
776750
IDENTITY_OP,
777751
INTEGER_DIVISION,
778-
CMP_NAN,
779752
CMP_OWNED,
780753
FLOAT_CMP,
781754
FLOAT_CMP_CONST,
@@ -816,7 +789,6 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
816789
duration_subsec::check(cx, e, op.node, lhs, rhs);
817790
float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
818791
integer_division::check(cx, e, op.node, lhs, rhs);
819-
cmp_nan::check(cx, e, op.node, lhs, rhs);
820792
cmp_owned::check(cx, op.node, lhs, rhs);
821793
float_cmp::check(cx, e, op.node, lhs, rhs);
822794
modulo_one::check(cx, e, op.node, rhs);

‎src/tools/clippy/clippy_lints/src/renamed_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
3333
("clippy::zero_width_space", "clippy::invisible_characters"),
3434
("clippy::cast_ref_to_mut", "cast_ref_to_mut"),
3535
("clippy::clone_double_ref", "suspicious_double_ref_op"),
36+
("clippy::cmp_nan", "invalid_nan_comparisons"),
3637
("clippy::drop_bounds", "drop_bounds"),
3738
("clippy::drop_copy", "dropping_copy_types"),
3839
("clippy::drop_ref", "dropping_references"),

‎src/tools/clippy/tests/ui/cmp_nan.rs

-34
This file was deleted.

‎src/tools/clippy/tests/ui/cmp_nan.stderr

-148
This file was deleted.

‎src/tools/clippy/tests/ui/crashes/mut_mut_macro.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)]
1+
#![deny(clippy::mut_mut, clippy::zero_ptr)]
22
#![allow(dead_code)]
33

44
// FIXME: compiletest + extern crates doesn't work together. To make this test work, it would need
@@ -8,13 +8,12 @@
88
// extern crate lazy_static;
99
// use std::collections::HashMap;
1010

11-
/// ensure that we don't suggest `is_nan` and `is_null` inside constants
11+
/// ensure that we don't suggest `is_null` inside constants
1212
/// FIXME: once const fn is stable, suggest these functions again in constants
1313
1414
const BAA: *const i32 = 0 as *const i32;
1515
static mut BAR: *const i32 = BAA;
1616
static mut FOO: *const i32 = 0 as *const i32;
17-
static mut BUH: bool = 42.0 < f32::NAN;
1817

1918
#[allow(unused_variables, unused_mut)]
2019
fn main() {

‎src/tools/clippy/tests/ui/rename.fixed

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#![allow(invalid_atomic_ordering)]
4242
#![allow(invalid_value)]
4343
#![allow(invalid_from_utf8_unchecked)]
44+
#![allow(invalid_nan_comparisons)]
4445
#![allow(let_underscore_drop)]
4546
#![allow(enum_intrinsics_non_enums)]
4647
#![allow(non_fmt_panics)]
@@ -55,6 +56,7 @@
5556
#![warn(clippy::blocks_in_if_conditions)]
5657
#![warn(clippy::blocks_in_if_conditions)]
5758
#![warn(clippy::box_collection)]
59+
#![warn(invalid_nan_comparisons)]
5860
#![warn(clippy::redundant_static_lifetimes)]
5961
#![warn(clippy::cognitive_complexity)]
6062
#![warn(clippy::derived_hash_with_manual_eq)]

‎src/tools/clippy/tests/ui/rename.rs

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#![allow(invalid_atomic_ordering)]
4242
#![allow(invalid_value)]
4343
#![allow(invalid_from_utf8_unchecked)]
44+
#![allow(invalid_nan_comparisons)]
4445
#![allow(let_underscore_drop)]
4546
#![allow(enum_intrinsics_non_enums)]
4647
#![allow(non_fmt_panics)]
@@ -55,6 +56,7 @@
5556
#![warn(clippy::block_in_if_condition_expr)]
5657
#![warn(clippy::block_in_if_condition_stmt)]
5758
#![warn(clippy::box_vec)]
59+
#![warn(clippy::cmp_nan)]
5860
#![warn(clippy::const_static_lifetime)]
5961
#![warn(clippy::cyclomatic_complexity)]
6062
#![warn(clippy::derive_hash_xor_eq)]
+58-52
Original file line numberDiff line numberDiff line change
@@ -1,310 +1,316 @@
11
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
2-
--> $DIR/rename.rs:53:9
2+
--> $DIR/rename.rs:54:9
33
|
44
LL | #![warn(clippy::almost_complete_letter_range)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
66
|
77
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
88

99
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
10-
--> $DIR/rename.rs:54:9
10+
--> $DIR/rename.rs:55:9
1111
|
1212
LL | #![warn(clippy::blacklisted_name)]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
1414

1515
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
16-
--> $DIR/rename.rs:55:9
16+
--> $DIR/rename.rs:56:9
1717
|
1818
LL | #![warn(clippy::block_in_if_condition_expr)]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
2020

2121
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
22-
--> $DIR/rename.rs:56:9
22+
--> $DIR/rename.rs:57:9
2323
|
2424
LL | #![warn(clippy::block_in_if_condition_stmt)]
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
2626

2727
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
28-
--> $DIR/rename.rs:57:9
28+
--> $DIR/rename.rs:58:9
2929
|
3030
LL | #![warn(clippy::box_vec)]
3131
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
3232

33+
error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
34+
--> $DIR/rename.rs:59:9
35+
|
36+
LL | #![warn(clippy::cmp_nan)]
37+
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
38+
3339
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
34-
--> $DIR/rename.rs:58:9
40+
--> $DIR/rename.rs:60:9
3541
|
3642
LL | #![warn(clippy::const_static_lifetime)]
3743
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
3844

3945
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
40-
--> $DIR/rename.rs:59:9
46+
--> $DIR/rename.rs:61:9
4147
|
4248
LL | #![warn(clippy::cyclomatic_complexity)]
4349
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
4450

4551
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
46-
--> $DIR/rename.rs:60:9
52+
--> $DIR/rename.rs:62:9
4753
|
4854
LL | #![warn(clippy::derive_hash_xor_eq)]
4955
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
5056

5157
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
52-
--> $DIR/rename.rs:61:9
58+
--> $DIR/rename.rs:63:9
5359
|
5460
LL | #![warn(clippy::disallowed_method)]
5561
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
5662

5763
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
58-
--> $DIR/rename.rs:62:9
64+
--> $DIR/rename.rs:64:9
5965
|
6066
LL | #![warn(clippy::disallowed_type)]
6167
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
6268

6369
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
64-
--> $DIR/rename.rs:63:9
70+
--> $DIR/rename.rs:65:9
6571
|
6672
LL | #![warn(clippy::eval_order_dependence)]
6773
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
6874

6975
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
70-
--> $DIR/rename.rs:64:9
76+
--> $DIR/rename.rs:66:9
7177
|
7278
LL | #![warn(clippy::identity_conversion)]
7379
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
7480

7581
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
76-
--> $DIR/rename.rs:65:9
82+
--> $DIR/rename.rs:67:9
7783
|
7884
LL | #![warn(clippy::if_let_some_result)]
7985
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
8086

8187
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
82-
--> $DIR/rename.rs:66:9
88+
--> $DIR/rename.rs:68:9
8389
|
8490
LL | #![warn(clippy::integer_arithmetic)]
8591
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
8692

8793
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
88-
--> $DIR/rename.rs:67:9
94+
--> $DIR/rename.rs:69:9
8995
|
9096
LL | #![warn(clippy::logic_bug)]
9197
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
9298

9399
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
94-
--> $DIR/rename.rs:68:9
100+
--> $DIR/rename.rs:70:9
95101
|
96102
LL | #![warn(clippy::new_without_default_derive)]
97103
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
98104

99105
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
100-
--> $DIR/rename.rs:69:9
106+
--> $DIR/rename.rs:71:9
101107
|
102108
LL | #![warn(clippy::option_and_then_some)]
103109
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
104110

105111
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
106-
--> $DIR/rename.rs:70:9
112+
--> $DIR/rename.rs:72:9
107113
|
108114
LL | #![warn(clippy::option_expect_used)]
109115
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
110116

111117
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
112-
--> $DIR/rename.rs:71:9
118+
--> $DIR/rename.rs:73:9
113119
|
114120
LL | #![warn(clippy::option_map_unwrap_or)]
115121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
116122

117123
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
118-
--> $DIR/rename.rs:72:9
124+
--> $DIR/rename.rs:74:9
119125
|
120126
LL | #![warn(clippy::option_map_unwrap_or_else)]
121127
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
122128

123129
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
124-
--> $DIR/rename.rs:73:9
130+
--> $DIR/rename.rs:75:9
125131
|
126132
LL | #![warn(clippy::option_unwrap_used)]
127133
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
128134

129135
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
130-
--> $DIR/rename.rs:74:9
136+
--> $DIR/rename.rs:76:9
131137
|
132138
LL | #![warn(clippy::ref_in_deref)]
133139
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
134140

135141
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
136-
--> $DIR/rename.rs:75:9
142+
--> $DIR/rename.rs:77:9
137143
|
138144
LL | #![warn(clippy::result_expect_used)]
139145
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
140146

141147
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
142-
--> $DIR/rename.rs:76:9
148+
--> $DIR/rename.rs:78:9
143149
|
144150
LL | #![warn(clippy::result_map_unwrap_or_else)]
145151
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
146152

147153
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
148-
--> $DIR/rename.rs:77:9
154+
--> $DIR/rename.rs:79:9
149155
|
150156
LL | #![warn(clippy::result_unwrap_used)]
151157
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
152158

153159
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
154-
--> $DIR/rename.rs:78:9
160+
--> $DIR/rename.rs:80:9
155161
|
156162
LL | #![warn(clippy::single_char_push_str)]
157163
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
158164

159165
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
160-
--> $DIR/rename.rs:79:9
166+
--> $DIR/rename.rs:81:9
161167
|
162168
LL | #![warn(clippy::stutter)]
163169
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
164170

165171
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
166-
--> $DIR/rename.rs:80:9
172+
--> $DIR/rename.rs:82:9
167173
|
168174
LL | #![warn(clippy::to_string_in_display)]
169175
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
170176

171177
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
172-
--> $DIR/rename.rs:81:9
178+
--> $DIR/rename.rs:83:9
173179
|
174180
LL | #![warn(clippy::zero_width_space)]
175181
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
176182

177183
error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
178-
--> $DIR/rename.rs:82:9
184+
--> $DIR/rename.rs:84:9
179185
|
180186
LL | #![warn(clippy::cast_ref_to_mut)]
181187
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
182188

183189
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
184-
--> $DIR/rename.rs:83:9
190+
--> $DIR/rename.rs:85:9
185191
|
186192
LL | #![warn(clippy::clone_double_ref)]
187193
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
188194

189195
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
190-
--> $DIR/rename.rs:84:9
196+
--> $DIR/rename.rs:86:9
191197
|
192198
LL | #![warn(clippy::drop_bounds)]
193199
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
194200

195201
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
196-
--> $DIR/rename.rs:85:9
202+
--> $DIR/rename.rs:87:9
197203
|
198204
LL | #![warn(clippy::drop_copy)]
199205
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
200206

201207
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
202-
--> $DIR/rename.rs:86:9
208+
--> $DIR/rename.rs:88:9
203209
|
204210
LL | #![warn(clippy::drop_ref)]
205211
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
206212

207213
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
208-
--> $DIR/rename.rs:87:9
214+
--> $DIR/rename.rs:89:9
209215
|
210216
LL | #![warn(clippy::for_loop_over_option)]
211217
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
212218

213219
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
214-
--> $DIR/rename.rs:88:9
220+
--> $DIR/rename.rs:90:9
215221
|
216222
LL | #![warn(clippy::for_loop_over_result)]
217223
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
218224

219225
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
220-
--> $DIR/rename.rs:89:9
226+
--> $DIR/rename.rs:91:9
221227
|
222228
LL | #![warn(clippy::for_loops_over_fallibles)]
223229
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
224230

225231
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
226-
--> $DIR/rename.rs:90:9
232+
--> $DIR/rename.rs:92:9
227233
|
228234
LL | #![warn(clippy::forget_copy)]
229235
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
230236

231237
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
232-
--> $DIR/rename.rs:91:9
238+
--> $DIR/rename.rs:93:9
233239
|
234240
LL | #![warn(clippy::forget_ref)]
235241
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
236242

237243
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
238-
--> $DIR/rename.rs:92:9
244+
--> $DIR/rename.rs:94:9
239245
|
240246
LL | #![warn(clippy::into_iter_on_array)]
241247
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
242248

243249
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
244-
--> $DIR/rename.rs:93:9
250+
--> $DIR/rename.rs:95:9
245251
|
246252
LL | #![warn(clippy::invalid_atomic_ordering)]
247253
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
248254

249255
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
250-
--> $DIR/rename.rs:94:9
256+
--> $DIR/rename.rs:96:9
251257
|
252258
LL | #![warn(clippy::invalid_ref)]
253259
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
254260

255261
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
256-
--> $DIR/rename.rs:95:9
262+
--> $DIR/rename.rs:97:9
257263
|
258264
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
259265
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
260266

261267
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
262-
--> $DIR/rename.rs:96:9
268+
--> $DIR/rename.rs:98:9
263269
|
264270
LL | #![warn(clippy::let_underscore_drop)]
265271
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
266272

267273
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
268-
--> $DIR/rename.rs:97:9
274+
--> $DIR/rename.rs:99:9
269275
|
270276
LL | #![warn(clippy::mem_discriminant_non_enum)]
271277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
272278

273279
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
274-
--> $DIR/rename.rs:98:9
280+
--> $DIR/rename.rs:100:9
275281
|
276282
LL | #![warn(clippy::panic_params)]
277283
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
278284

279285
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
280-
--> $DIR/rename.rs:99:9
286+
--> $DIR/rename.rs:101:9
281287
|
282288
LL | #![warn(clippy::positional_named_format_parameters)]
283289
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
284290

285291
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
286-
--> $DIR/rename.rs:100:9
292+
--> $DIR/rename.rs:102:9
287293
|
288294
LL | #![warn(clippy::temporary_cstring_as_ptr)]
289295
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
290296

291297
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
292-
--> $DIR/rename.rs:101:9
298+
--> $DIR/rename.rs:103:9
293299
|
294300
LL | #![warn(clippy::undropped_manually_drops)]
295301
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
296302

297303
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
298-
--> $DIR/rename.rs:102:9
304+
--> $DIR/rename.rs:104:9
299305
|
300306
LL | #![warn(clippy::unknown_clippy_lints)]
301307
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
302308

303309
error: lint `clippy::unused_label` has been renamed to `unused_labels`
304-
--> $DIR/rename.rs:103:9
310+
--> $DIR/rename.rs:105:9
305311
|
306312
LL | #![warn(clippy::unused_label)]
307313
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
308314

309-
error: aborting due to 51 previous errors
315+
error: aborting due to 52 previous errors
310316

‎src/tools/clippy/tests/ui/unknown_clippy_lints.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![warn(clippy::pedantic)]
44
// Should suggest lowercase
55
#![allow(clippy::all)]
6-
#![warn(clippy::cmp_nan)]
6+
#![warn(clippy::cmp_owned)]
77

88
// Should suggest similar clippy lint name
99
#[warn(clippy::if_not_else)]

‎src/tools/clippy/tests/ui/unknown_clippy_lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![warn(clippy::pedantic)]
44
// Should suggest lowercase
55
#![allow(clippy::All)]
6-
#![warn(clippy::CMP_NAN)]
6+
#![warn(clippy::CMP_OWNED)]
77

88
// Should suggest similar clippy lint name
99
#[warn(clippy::if_not_els)]

‎src/tools/clippy/tests/ui/unknown_clippy_lints.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ LL | #![allow(clippy::All)]
66
|
77
= note: `-D unknown-lints` implied by `-D warnings`
88

9-
error: unknown lint: `clippy::CMP_NAN`
9+
error: unknown lint: `clippy::CMP_OWNED`
1010
--> $DIR/unknown_clippy_lints.rs:6:9
1111
|
12-
LL | #![warn(clippy::CMP_NAN)]
13-
| ^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_nan`
12+
LL | #![warn(clippy::CMP_OWNED)]
13+
| ^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_owned`
1414

1515
error: unknown lint: `clippy::if_not_els`
1616
--> $DIR/unknown_clippy_lints.rs:9:8

‎tests/ui/issues/issue-50811.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// run-pass
22
#![feature(test)]
3+
#![allow(invalid_nan_comparisons)]
34

45
extern crate test;
56

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// check-pass
2+
// run-rustfix
3+
4+
fn main() {
5+
let x = 5f32;
6+
let _ = x.is_nan();
7+
//~^ WARN incorrect NaN comparison
8+
let _ = !x.is_nan();
9+
//~^ WARN incorrect NaN comparison
10+
11+
let x = 5f64;
12+
let _ = x.is_nan();
13+
//~^ WARN incorrect NaN comparison
14+
let _ = !x.is_nan();
15+
//~^ WARN incorrect NaN comparison
16+
17+
let b = &2.3f32;
18+
if !b.is_nan() {}
19+
//~^ WARN incorrect NaN comparison
20+
21+
let b = &2.3f32;
22+
if !b.is_nan() {}
23+
//~^ WARN incorrect NaN comparison
24+
25+
let _ =
26+
!b.is_nan();
27+
28+
#[allow(unused_macros)]
29+
macro_rules! nan { () => { f32::NAN }; }
30+
macro_rules! number { () => { 5f32 }; }
31+
32+
let _ = number!().is_nan();
33+
//~^ WARN incorrect NaN comparison
34+
let _ = !number!().is_nan();
35+
//~^ WARN incorrect NaN comparison
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
// run-rustfix
3+
4+
fn main() {
5+
let x = 5f32;
6+
let _ = x == f32::NAN;
7+
//~^ WARN incorrect NaN comparison
8+
let _ = x != f32::NAN;
9+
//~^ WARN incorrect NaN comparison
10+
11+
let x = 5f64;
12+
let _ = x == f64::NAN;
13+
//~^ WARN incorrect NaN comparison
14+
let _ = x != f64::NAN;
15+
//~^ WARN incorrect NaN comparison
16+
17+
let b = &2.3f32;
18+
if b != &f32::NAN {}
19+
//~^ WARN incorrect NaN comparison
20+
21+
let b = &2.3f32;
22+
if b != { &f32::NAN } {}
23+
//~^ WARN incorrect NaN comparison
24+
25+
let _ =
26+
b != {
27+
//~^ WARN incorrect NaN comparison
28+
&f32::NAN
29+
};
30+
31+
#[allow(unused_macros)]
32+
macro_rules! nan { () => { f32::NAN }; }
33+
macro_rules! number { () => { 5f32 }; }
34+
35+
let _ = nan!() == number!();
36+
//~^ WARN incorrect NaN comparison
37+
let _ = number!() != nan!();
38+
//~^ WARN incorrect NaN comparison
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
2+
--> $DIR/invalid-nan-comparison-suggestion.rs:6:13
3+
|
4+
LL | let _ = x == f32::NAN;
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(invalid_nan_comparisons)]` on by default
8+
help: use `f32::is_nan()` or `f64::is_nan()` instead
9+
|
10+
LL - let _ = x == f32::NAN;
11+
LL + let _ = x.is_nan();
12+
|
13+
14+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
15+
--> $DIR/invalid-nan-comparison-suggestion.rs:8:13
16+
|
17+
LL | let _ = x != f32::NAN;
18+
| ^^^^^^^^^^^^^
19+
|
20+
help: use `f32::is_nan()` or `f64::is_nan()` instead
21+
|
22+
LL - let _ = x != f32::NAN;
23+
LL + let _ = !x.is_nan();
24+
|
25+
26+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
27+
--> $DIR/invalid-nan-comparison-suggestion.rs:12:13
28+
|
29+
LL | let _ = x == f64::NAN;
30+
| ^^^^^^^^^^^^^
31+
|
32+
help: use `f32::is_nan()` or `f64::is_nan()` instead
33+
|
34+
LL - let _ = x == f64::NAN;
35+
LL + let _ = x.is_nan();
36+
|
37+
38+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
39+
--> $DIR/invalid-nan-comparison-suggestion.rs:14:13
40+
|
41+
LL | let _ = x != f64::NAN;
42+
| ^^^^^^^^^^^^^
43+
|
44+
help: use `f32::is_nan()` or `f64::is_nan()` instead
45+
|
46+
LL - let _ = x != f64::NAN;
47+
LL + let _ = !x.is_nan();
48+
|
49+
50+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
51+
--> $DIR/invalid-nan-comparison-suggestion.rs:18:8
52+
|
53+
LL | if b != &f32::NAN {}
54+
| ^^^^^^^^^^^^^^
55+
|
56+
help: use `f32::is_nan()` or `f64::is_nan()` instead
57+
|
58+
LL - if b != &f32::NAN {}
59+
LL + if !b.is_nan() {}
60+
|
61+
62+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
63+
--> $DIR/invalid-nan-comparison-suggestion.rs:22:8
64+
|
65+
LL | if b != { &f32::NAN } {}
66+
| ^^^^^^^^^^^^^^^^^^
67+
|
68+
help: use `f32::is_nan()` or `f64::is_nan()` instead
69+
|
70+
LL - if b != { &f32::NAN } {}
71+
LL + if !b.is_nan() {}
72+
|
73+
74+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
75+
--> $DIR/invalid-nan-comparison-suggestion.rs:26:9
76+
|
77+
LL | / b != {
78+
LL | |
79+
LL | | &f32::NAN
80+
LL | | };
81+
| |_________^
82+
|
83+
help: use `f32::is_nan()` or `f64::is_nan()` instead
84+
|
85+
LL - b != {
86+
LL + !b.is_nan();
87+
|
88+
89+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
90+
--> $DIR/invalid-nan-comparison-suggestion.rs:35:13
91+
|
92+
LL | let _ = nan!() == number!();
93+
| ^^^^^^^^^^^^^^^^^^^
94+
|
95+
help: use `f32::is_nan()` or `f64::is_nan()` instead
96+
|
97+
LL - let _ = nan!() == number!();
98+
LL + let _ = number!().is_nan();
99+
|
100+
101+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
102+
--> $DIR/invalid-nan-comparison-suggestion.rs:37:13
103+
|
104+
LL | let _ = number!() != nan!();
105+
| ^^^^^^^^^^^^^^^^^^^
106+
|
107+
help: use `f32::is_nan()` or `f64::is_nan()` instead
108+
|
109+
LL - let _ = number!() != nan!();
110+
LL + let _ = !number!().is_nan();
111+
|
112+
113+
warning: 9 warnings emitted
114+
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// check-pass
2+
3+
fn main() {
4+
f32();
5+
f64();
6+
}
7+
8+
const TEST: bool = 5f32 == f32::NAN;
9+
//~^ WARN incorrect NaN comparison
10+
11+
fn f32() {
12+
macro_rules! number { () => { 5f32 }; }
13+
let x = number!();
14+
x == f32::NAN;
15+
//~^ WARN incorrect NaN comparison
16+
x != f32::NAN;
17+
//~^ WARN incorrect NaN comparison
18+
x < f32::NAN;
19+
//~^ WARN incorrect NaN comparison
20+
x > f32::NAN;
21+
//~^ WARN incorrect NaN comparison
22+
x <= f32::NAN;
23+
//~^ WARN incorrect NaN comparison
24+
x >= f32::NAN;
25+
//~^ WARN incorrect NaN comparison
26+
number!() == f32::NAN;
27+
//~^ WARN incorrect NaN comparison
28+
f32::NAN != number!();
29+
//~^ WARN incorrect NaN comparison
30+
}
31+
32+
fn f64() {
33+
macro_rules! number { () => { 5f64 }; }
34+
let x = number!();
35+
x == f64::NAN;
36+
//~^ WARN incorrect NaN comparison
37+
x != f64::NAN;
38+
//~^ WARN incorrect NaN comparison
39+
x < f64::NAN;
40+
//~^ WARN incorrect NaN comparison
41+
x > f64::NAN;
42+
//~^ WARN incorrect NaN comparison
43+
x <= f64::NAN;
44+
//~^ WARN incorrect NaN comparison
45+
x >= f64::NAN;
46+
//~^ WARN incorrect NaN comparison
47+
number!() == f64::NAN;
48+
//~^ WARN incorrect NaN comparison
49+
f64::NAN != number!();
50+
//~^ WARN incorrect NaN comparison
51+
}
+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
2+
--> $DIR/invalid-nan-comparison.rs:8:20
3+
|
4+
LL | const TEST: bool = 5f32 == f32::NAN;
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= 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+
|
13+
14+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
15+
--> $DIR/invalid-nan-comparison.rs:14:5
16+
|
17+
LL | x == f32::NAN;
18+
| ^^^^^^^^^^^^^
19+
|
20+
help: use `f32::is_nan()` or `f64::is_nan()` instead
21+
|
22+
LL - x == f32::NAN;
23+
LL + x.is_nan();
24+
|
25+
26+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
27+
--> $DIR/invalid-nan-comparison.rs:16:5
28+
|
29+
LL | x != f32::NAN;
30+
| ^^^^^^^^^^^^^
31+
|
32+
help: use `f32::is_nan()` or `f64::is_nan()` instead
33+
|
34+
LL - x != f32::NAN;
35+
LL + !x.is_nan();
36+
|
37+
38+
warning: incorrect NaN comparison, NaN is not orderable
39+
--> $DIR/invalid-nan-comparison.rs:18:5
40+
|
41+
LL | x < f32::NAN;
42+
| ^^^^^^^^^^^^
43+
44+
warning: incorrect NaN comparison, NaN is not orderable
45+
--> $DIR/invalid-nan-comparison.rs:20:5
46+
|
47+
LL | x > f32::NAN;
48+
| ^^^^^^^^^^^^
49+
50+
warning: incorrect NaN comparison, NaN is not orderable
51+
--> $DIR/invalid-nan-comparison.rs:22:5
52+
|
53+
LL | x <= f32::NAN;
54+
| ^^^^^^^^^^^^^
55+
56+
warning: incorrect NaN comparison, NaN is not orderable
57+
--> $DIR/invalid-nan-comparison.rs:24:5
58+
|
59+
LL | x >= f32::NAN;
60+
| ^^^^^^^^^^^^^
61+
62+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
63+
--> $DIR/invalid-nan-comparison.rs:26:5
64+
|
65+
LL | number!() == f32::NAN;
66+
| ^^^^^^^^^^^^^^^^^^^^^
67+
|
68+
help: use `f32::is_nan()` or `f64::is_nan()` instead
69+
|
70+
LL - number!() == f32::NAN;
71+
LL + number!().is_nan();
72+
|
73+
74+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
75+
--> $DIR/invalid-nan-comparison.rs:28:5
76+
|
77+
LL | f32::NAN != number!();
78+
| ^^^^^^^^^^^^^^^^^^^^^
79+
|
80+
help: use `f32::is_nan()` or `f64::is_nan()` instead
81+
|
82+
LL - f32::NAN != number!();
83+
LL + !number!().is_nan();
84+
|
85+
86+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
87+
--> $DIR/invalid-nan-comparison.rs:35:5
88+
|
89+
LL | x == f64::NAN;
90+
| ^^^^^^^^^^^^^
91+
|
92+
help: use `f32::is_nan()` or `f64::is_nan()` instead
93+
|
94+
LL - x == f64::NAN;
95+
LL + x.is_nan();
96+
|
97+
98+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
99+
--> $DIR/invalid-nan-comparison.rs:37:5
100+
|
101+
LL | x != f64::NAN;
102+
| ^^^^^^^^^^^^^
103+
|
104+
help: use `f32::is_nan()` or `f64::is_nan()` instead
105+
|
106+
LL - x != f64::NAN;
107+
LL + !x.is_nan();
108+
|
109+
110+
warning: incorrect NaN comparison, NaN is not orderable
111+
--> $DIR/invalid-nan-comparison.rs:39:5
112+
|
113+
LL | x < f64::NAN;
114+
| ^^^^^^^^^^^^
115+
116+
warning: incorrect NaN comparison, NaN is not orderable
117+
--> $DIR/invalid-nan-comparison.rs:41:5
118+
|
119+
LL | x > f64::NAN;
120+
| ^^^^^^^^^^^^
121+
122+
warning: incorrect NaN comparison, NaN is not orderable
123+
--> $DIR/invalid-nan-comparison.rs:43:5
124+
|
125+
LL | x <= f64::NAN;
126+
| ^^^^^^^^^^^^^
127+
128+
warning: incorrect NaN comparison, NaN is not orderable
129+
--> $DIR/invalid-nan-comparison.rs:45:5
130+
|
131+
LL | x >= f64::NAN;
132+
| ^^^^^^^^^^^^^
133+
134+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
135+
--> $DIR/invalid-nan-comparison.rs:47:5
136+
|
137+
LL | number!() == f64::NAN;
138+
| ^^^^^^^^^^^^^^^^^^^^^
139+
|
140+
help: use `f32::is_nan()` or `f64::is_nan()` instead
141+
|
142+
LL - number!() == f64::NAN;
143+
LL + number!().is_nan();
144+
|
145+
146+
warning: incorrect NaN comparison, NaN cannot be directly compared to itself
147+
--> $DIR/invalid-nan-comparison.rs:49:5
148+
|
149+
LL | f64::NAN != number!();
150+
| ^^^^^^^^^^^^^^^^^^^^^
151+
|
152+
help: use `f32::is_nan()` or `f64::is_nan()` instead
153+
|
154+
LL - f64::NAN != number!();
155+
LL + !number!().is_nan();
156+
|
157+
158+
warning: 17 warnings emitted
159+

0 commit comments

Comments
 (0)
Please sign in to comment.