about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-02-25 09:20:55 +0100
committerSamuel Tardieu <sam@rfc1149.net>2025-06-20 09:42:27 +0200
commit0fdd0b928ed391f89ba4aec6714a1ca4dd67cefd (patch)
treeb6eccf29c803cdae733d2c8085478b9748de809b
parent8ec6f1a96f471a72e7cfed072b5eb4f4b85bc6d6 (diff)
downloadrust-0fdd0b928ed391f89ba4aec6714a1ca4dd67cefd.tar.gz
rust-0fdd0b928ed391f89ba4aec6714a1ca4dd67cefd.zip
Add `integer_const()` and `is_zero_integer_const()` utility functions
-rw-r--r--clippy_lints/src/if_not_else.rs11
-rw-r--r--clippy_lints/src/operators/identity_op.rs6
-rw-r--r--clippy_utils/src/consts.rs15
3 files changed, 19 insertions, 13 deletions
diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs
index 45f9aa0a53e..ab7a965b367 100644
--- a/clippy_lints/src/if_not_else.rs
+++ b/clippy_lints/src/if_not_else.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::consts::is_zero_integer_const;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::is_else_clause;
 use clippy_utils::source::{HasSession, indent_of, reindent_multiline, snippet};
@@ -48,13 +48,6 @@ declare_clippy_lint! {
 
 declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
 
-fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
-    if let Some(value) = ConstEvalCtxt::new(cx).eval_simple(expr) {
-        return Constant::Int(0) == value;
-    }
-    false
-}
-
 impl LateLintPass<'_> for IfNotElse {
     fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
         if let ExprKind::If(cond, cond_inner, Some(els)) = e.kind
@@ -68,7 +61,7 @@ impl LateLintPass<'_> for IfNotElse {
                 ),
                 // Don't lint on `… != 0`, as these are likely to be bit tests.
                 // For example, `if foo & 0x0F00 != 0 { … } else { … }` is already in the "proper" order.
-                ExprKind::Binary(op, _, rhs) if op.node == BinOpKind::Ne && !is_zero_const(rhs, cx) => (
+                ExprKind::Binary(op, _, rhs) if op.node == BinOpKind::Ne && !is_zero_integer_const(cx, rhs) => (
                     "unnecessary `!=` operation",
                     "change to `==` and swap the blocks of the `if`/`else`",
                 ),
diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs
index 7e515e83cc9..3efbb896358 100644
--- a/clippy_lints/src/operators/identity_op.rs
+++ b/clippy_lints/src/operators/identity_op.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt, integer_const, is_zero_integer_const};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{ExprUseNode, clip, expr_use_ctxt, peel_hir_expr_refs, unsext};
@@ -186,9 +186,7 @@ fn is_allowed<'tcx>(
     cx.typeck_results().expr_ty(left).peel_refs().is_integral()
         && cx.typeck_results().expr_ty(right).peel_refs().is_integral()
         // `1 << 0` is a common pattern in bit manipulation code
-        && !(cmp == BinOpKind::Shl
-            && ConstEvalCtxt::new(cx).eval_simple(right) == Some(Constant::Int(0))
-            && ConstEvalCtxt::new(cx).eval_simple(left) == Some(Constant::Int(1)))
+        && !(cmp == BinOpKind::Shl && is_zero_integer_const(cx, right) && integer_const(cx, left) == Some(1))
 }
 
 fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) {
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 1ec5d11384f..aaa071fd5c9 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -958,3 +958,18 @@ fn field_of_struct<'tcx>(
         None
     }
 }
+
+/// If `expr` evaluates to an integer constant, return its value.
+pub fn integer_const(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
+    if let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_simple(expr) {
+        Some(value)
+    } else {
+        None
+    }
+}
+
+/// Check if `expr` evaluates to an integer constant of 0.
+#[inline]
+pub fn is_zero_integer_const(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    integer_const(cx, expr) == Some(0)
+}