about summary refs log tree commit diff
path: root/clippy_lints/src/operators
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2024-02-08 20:24:42 +0100
committerPhilipp Krones <hello@philkrones.com>2024-02-08 20:24:42 +0100
commitf3b3d23416f1da77103bb74788f23b4f9c78ee7e (patch)
tree06eefe8d8b7243b2639abd38cf3c35469736a84e /clippy_lints/src/operators
parent7a827028a59187bbe5558b27bedb9c00b144fa8e (diff)
Merge commit '60cb29c5e4f9772685c9873752196725c946a849' into clippyup
Diffstat (limited to 'clippy_lints/src/operators')
-rw-r--r--clippy_lints/src/operators/mod.rs15
-rw-r--r--clippy_lints/src/operators/modulo_arithmetic.rs27
2 files changed, 38 insertions, 4 deletions
diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs
index 4c09c4eea58..e002429e3a4 100644
--- a/clippy_lints/src/operators/mod.rs
+++ b/clippy_lints/src/operators/mod.rs
@@ -771,6 +771,7 @@ declare_clippy_lint! {
 pub struct Operators {
     arithmetic_context: numeric_arithmetic::Context,
     verbose_bit_mask_threshold: u64,
+    modulo_arithmetic_allow_comparison_to_zero: bool,
 }
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
@@ -801,10 +802,11 @@ impl_lint_pass!(Operators => [
     SELF_ASSIGNMENT,
 ]);
 impl Operators {
-    pub fn new(verbose_bit_mask_threshold: u64) -> Self {
+    pub fn new(verbose_bit_mask_threshold: u64, modulo_arithmetic_allow_comparison_to_zero: bool) -> Self {
         Self {
             arithmetic_context: numeric_arithmetic::Context::default(),
             verbose_bit_mask_threshold,
+            modulo_arithmetic_allow_comparison_to_zero,
         }
     }
 }
@@ -835,12 +837,19 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
                 cmp_owned::check(cx, op.node, lhs, rhs);
                 float_cmp::check(cx, e, op.node, lhs, rhs);
                 modulo_one::check(cx, e, op.node, rhs);
-                modulo_arithmetic::check(cx, e, op.node, lhs, rhs);
+                modulo_arithmetic::check(
+                    cx,
+                    e,
+                    op.node,
+                    lhs,
+                    rhs,
+                    self.modulo_arithmetic_allow_comparison_to_zero,
+                );
             },
             ExprKind::AssignOp(op, lhs, rhs) => {
                 self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
                 misrefactored_assign_op::check(cx, e, op.node, lhs, rhs);
-                modulo_arithmetic::check(cx, e, op.node, lhs, rhs);
+                modulo_arithmetic::check(cx, e, op.node, lhs, rhs, false);
             },
             ExprKind::Assign(lhs, rhs, _) => {
                 assign_op_pattern::check(cx, e, lhs, rhs);
diff --git a/clippy_lints/src/operators/modulo_arithmetic.rs b/clippy_lints/src/operators/modulo_arithmetic.rs
index cb3916484c1..40d4a842bef 100644
--- a/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -1,7 +1,7 @@
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sext;
-use rustc_hir::{BinOpKind, Expr};
+use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 use std::fmt::Display;
@@ -14,8 +14,13 @@ pub(super) fn check<'tcx>(
     op: BinOpKind,
     lhs: &'tcx Expr<'_>,
     rhs: &'tcx Expr<'_>,
+    allow_comparison_to_zero: bool,
 ) {
     if op == BinOpKind::Rem {
+        if allow_comparison_to_zero && used_in_comparison_with_zero(cx, e) {
+            return;
+        }
+
         let lhs_operand = analyze_operand(lhs, cx, e);
         let rhs_operand = analyze_operand(rhs, cx, e);
         if let Some(lhs_operand) = lhs_operand
@@ -28,6 +33,26 @@ pub(super) fn check<'tcx>(
     };
 }
 
+fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find_parent(expr.hir_id) else {
+        return false;
+    };
+    let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind else {
+        return false;
+    };
+
+    if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne {
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), rhs) {
+            return true;
+        }
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), lhs) {
+            return true;
+        }
+    }
+
+    false
+}
+
 struct OperandInfo {
     string_representation: Option<String>,
     is_negative: bool,