about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/if_not_else.rs12
-rw-r--r--tests/ui/if_not_else_bittest.rs11
2 files changed, 22 insertions, 1 deletions
diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs
index 3d59b783337..640819890b9 100644
--- a/clippy_lints/src/if_not_else.rs
+++ b/clippy_lints/src/if_not_else.rs
@@ -1,6 +1,7 @@
 //! lint on if branches that could be swapped so no `!` operation is necessary
 //! on the condition
 
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_else_clause;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@@ -47,6 +48,13 @@ declare_clippy_lint! {
 
 declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
 
+fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
+    if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) {
+        return Constant::Int(0) == value;
+    }
+    false
+}
+
 impl LateLintPass<'_> for IfNotElse {
     fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
         // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
@@ -72,7 +80,9 @@ impl LateLintPass<'_> for IfNotElse {
                             "remove the `!` and swap the blocks of the `if`/`else`",
                         );
                     },
-                    ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => {
+                    ExprKind::Binary(ref kind, _, lhs) if kind.node == BinOpKind::Ne && !is_zero_const(lhs, cx) => {
+                        // Disable firing the lint on `… != 0`, as these are likely to be bit tests.
+                        // For example, `if foo & 0x0F00 != 0 { … } else { … }` already is in the "proper" order.
                         span_lint_and_help(
                             cx,
                             IF_NOT_ELSE,
diff --git a/tests/ui/if_not_else_bittest.rs b/tests/ui/if_not_else_bittest.rs
new file mode 100644
index 00000000000..586ce6ce1bc
--- /dev/null
+++ b/tests/ui/if_not_else_bittest.rs
@@ -0,0 +1,11 @@
+#![deny(clippy::if_not_else)]
+
+fn show_permissions(flags: u32) {
+    if flags & 0x0F00 != 0 {
+        println!("Has the 0x0F00 permission.");
+    } else {
+        println!("The 0x0F00 permission is missing.");
+    }
+}
+
+fn main() {}