Skip to content

Commit

Permalink
Auto merge of rust-lang#12765 - yusufraji:while-float, r=llogiq
Browse files Browse the repository at this point in the history
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 rust-lang#758
  • Loading branch information
bors committed May 21, 2024
2 parents 0b1bf37 + cb3fcbb commit 2efebd2
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5911,6 +5911,7 @@ Released 2018-09-13
[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
[`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake
[`while_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_float
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::loops::SAME_ITEM_PUSH_INFO,
crate::loops::SINGLE_ELEMENT_LOOP_INFO,
crate::loops::UNUSED_ENUMERATE_INDEX_INFO,
crate::loops::WHILE_FLOAT_INFO,
crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
crate::loops::WHILE_LET_LOOP_INFO,
crate::loops::WHILE_LET_ON_ITERATOR_INFO,
Expand Down
36 changes: 36 additions & 0 deletions clippy_lints/src/loops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod same_item_push;
mod single_element_loop;
mod unused_enumerate_index;
mod utils;
mod while_float;
mod while_immutable_condition;
mod while_let_loop;
mod while_let_on_iterator;
Expand Down Expand Up @@ -416,6 +417,39 @@ declare_clippy_lint! {
"variables used within while expression are not mutated in the body"
}

declare_clippy_lint! {
/// ### What it does
/// Checks for while loops comparing floating point values.
///
/// ### Why is this bad?
/// If you increment floating point values, errors can compound,
/// so, use integers instead if possible.
///
/// ### Known problems
/// The lint will catch all while loops comparing floating point
/// values without regarding the increment.
///
/// ### Example
/// ```no_run
/// let mut x = 0.0;
/// while x < 42.0 {
/// x += 1.0;
/// }
/// ```
///
/// Use instead:
/// ```no_run
/// let mut x = 0;
/// while x < 42 {
/// x += 1;
/// }
/// ```
#[clippy::version = "1.80.0"]
pub WHILE_FLOAT,
nursery,
"while loops comaparing floating point values"
}

declare_clippy_lint! {
/// ### What it does
/// Checks whether a for loop is being used to push a constant
Expand Down Expand Up @@ -706,6 +740,7 @@ impl_lint_pass!(Loops => [
NEVER_LOOP,
MUT_RANGE_BOUND,
WHILE_IMMUTABLE_CONDITION,
WHILE_FLOAT,
SAME_ITEM_PUSH,
SINGLE_ELEMENT_LOOP,
MISSING_SPIN_LOOP,
Expand Down Expand Up @@ -762,6 +797,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {

if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) {
while_immutable_condition::check(cx, condition, body);
while_float::check(cx, condition);
missing_spin_loop::check(cx, condition, body);
manual_while_let_some::check(cx, condition, body, span);
}
Expand Down
20 changes: 20 additions & 0 deletions clippy_lints/src/loops/while_float.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::ExprKind;

pub(super) fn check(cx: &rustc_lint::LateContext<'_>, condition: &rustc_hir::Expr<'_>) {
if let ExprKind::Binary(_op, left, right) = condition.kind
&& is_float_type(cx, left)
&& is_float_type(cx, right)
{
span_lint(
cx,
super::WHILE_FLOAT,
condition.span,
"while condition comparing floats",
);
}
}

fn is_float_type(cx: &rustc_lint::LateContext<'_>, expr: &rustc_hir::Expr<'_>) -> bool {
cx.typeck_results().expr_ty(expr).is_floating_point()
}
14 changes: 14 additions & 0 deletions tests/ui/while_float.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[deny(clippy::while_float)]
fn main() {
let mut x = 0.0_f32;
while x < 42.0_f32 {
x += 0.5;
}
while x < 42.0 {
x += 1.0;
}
let mut x = 0;
while x < 42 {
x += 1;
}
}
20 changes: 20 additions & 0 deletions tests/ui/while_float.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: while condition comparing floats
--> tests/ui/while_float.rs:4:11
|
LL | while x < 42.0_f32 {
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/while_float.rs:1:8
|
LL | #[deny(clippy::while_float)]
| ^^^^^^^^^^^^^^^^^^^

error: while condition comparing floats
--> tests/ui/while_float.rs:7:11
|
LL | while x < 42.0 {
| ^^^^^^^^

error: aborting due to 2 previous errors

0 comments on commit 2efebd2

Please sign in to comment.