Skip to content

Commit 2efebd2

Browse files
committed
Auto merge of #12765 - yusufraji:while-float, r=llogiq
Add new lint `while_float` This PR adds a nursery lint that checks for while loops comparing floating point values. changelog: ``` changelog: [`while_float`]: Checks for while loops comparing floating point values. ``` Fixes #758
2 parents 0b1bf37 + cb3fcbb commit 2efebd2

File tree

6 files changed

+92
-0
lines changed

6 files changed

+92
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5911,6 +5911,7 @@ Released 2018-09-13
59115911
[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
59125912
[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
59135913
[`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake
5914+
[`while_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_float
59145915
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
59155916
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
59165917
[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator

clippy_lints/src/declared_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
293293
crate::loops::SAME_ITEM_PUSH_INFO,
294294
crate::loops::SINGLE_ELEMENT_LOOP_INFO,
295295
crate::loops::UNUSED_ENUMERATE_INDEX_INFO,
296+
crate::loops::WHILE_FLOAT_INFO,
296297
crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
297298
crate::loops::WHILE_LET_LOOP_INFO,
298299
crate::loops::WHILE_LET_ON_ITERATOR_INFO,

clippy_lints/src/loops/mod.rs

+36
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod same_item_push;
1717
mod single_element_loop;
1818
mod unused_enumerate_index;
1919
mod utils;
20+
mod while_float;
2021
mod while_immutable_condition;
2122
mod while_let_loop;
2223
mod while_let_on_iterator;
@@ -416,6 +417,39 @@ declare_clippy_lint! {
416417
"variables used within while expression are not mutated in the body"
417418
}
418419

420+
declare_clippy_lint! {
421+
/// ### What it does
422+
/// Checks for while loops comparing floating point values.
423+
///
424+
/// ### Why is this bad?
425+
/// If you increment floating point values, errors can compound,
426+
/// so, use integers instead if possible.
427+
///
428+
/// ### Known problems
429+
/// The lint will catch all while loops comparing floating point
430+
/// values without regarding the increment.
431+
///
432+
/// ### Example
433+
/// ```no_run
434+
/// let mut x = 0.0;
435+
/// while x < 42.0 {
436+
/// x += 1.0;
437+
/// }
438+
/// ```
439+
///
440+
/// Use instead:
441+
/// ```no_run
442+
/// let mut x = 0;
443+
/// while x < 42 {
444+
/// x += 1;
445+
/// }
446+
/// ```
447+
#[clippy::version = "1.80.0"]
448+
pub WHILE_FLOAT,
449+
nursery,
450+
"while loops comaparing floating point values"
451+
}
452+
419453
declare_clippy_lint! {
420454
/// ### What it does
421455
/// Checks whether a for loop is being used to push a constant
@@ -706,6 +740,7 @@ impl_lint_pass!(Loops => [
706740
NEVER_LOOP,
707741
MUT_RANGE_BOUND,
708742
WHILE_IMMUTABLE_CONDITION,
743+
WHILE_FLOAT,
709744
SAME_ITEM_PUSH,
710745
SINGLE_ELEMENT_LOOP,
711746
MISSING_SPIN_LOOP,
@@ -762,6 +797,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
762797

763798
if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) {
764799
while_immutable_condition::check(cx, condition, body);
800+
while_float::check(cx, condition);
765801
missing_spin_loop::check(cx, condition, body);
766802
manual_while_let_some::check(cx, condition, body, span);
767803
}

clippy_lints/src/loops/while_float.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use rustc_hir::ExprKind;
3+
4+
pub(super) fn check(cx: &rustc_lint::LateContext<'_>, condition: &rustc_hir::Expr<'_>) {
5+
if let ExprKind::Binary(_op, left, right) = condition.kind
6+
&& is_float_type(cx, left)
7+
&& is_float_type(cx, right)
8+
{
9+
span_lint(
10+
cx,
11+
super::WHILE_FLOAT,
12+
condition.span,
13+
"while condition comparing floats",
14+
);
15+
}
16+
}
17+
18+
fn is_float_type(cx: &rustc_lint::LateContext<'_>, expr: &rustc_hir::Expr<'_>) -> bool {
19+
cx.typeck_results().expr_ty(expr).is_floating_point()
20+
}

tests/ui/while_float.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#[deny(clippy::while_float)]
2+
fn main() {
3+
let mut x = 0.0_f32;
4+
while x < 42.0_f32 {
5+
x += 0.5;
6+
}
7+
while x < 42.0 {
8+
x += 1.0;
9+
}
10+
let mut x = 0;
11+
while x < 42 {
12+
x += 1;
13+
}
14+
}

tests/ui/while_float.stderr

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: while condition comparing floats
2+
--> tests/ui/while_float.rs:4:11
3+
|
4+
LL | while x < 42.0_f32 {
5+
| ^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> tests/ui/while_float.rs:1:8
9+
|
10+
LL | #[deny(clippy::while_float)]
11+
| ^^^^^^^^^^^^^^^^^^^
12+
13+
error: while condition comparing floats
14+
--> tests/ui/while_float.rs:7:11
15+
|
16+
LL | while x < 42.0 {
17+
| ^^^^^^^^
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)