From 5e17f9f97252d52515b9a6eb75dd6cc8b5ecb70f Mon Sep 17 00:00:00 2001 From: Ben Wiederhake Date: Sun, 25 Jun 2023 12:15:18 +0200 Subject: [PATCH] Skip if_not_else lint for '!= 0'-style checks --- clippy_lints/src/if_not_else.rs | 12 +++++++++++- tests/ui/if_not_else_bittest.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/ui/if_not_else_bittest.rs diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 3d59b7833..640819890 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 000000000..586ce6ce1 --- /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() {}