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
This commit is contained in:
bors 2024-05-21 11:36:31 +00:00
commit 2efebd2f0c
6 changed files with 92 additions and 0 deletions

View file

@ -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;
@ -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
@ -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,
@ -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);
}

View file

@ -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()
}