1
1
//! lint on if branches that could be swapped so no `!` operation is necessary
2
2
//! on the condition
3
3
4
+ use clippy_utils:: consts:: { constant_simple, Constant } ;
4
5
use clippy_utils:: diagnostics:: span_lint_and_help;
5
6
use clippy_utils:: is_else_clause;
6
7
use rustc_hir:: { BinOpKind , Expr , ExprKind , UnOp } ;
@@ -47,6 +48,13 @@ declare_clippy_lint! {
47
48
48
49
declare_lint_pass ! ( IfNotElse => [ IF_NOT_ELSE ] ) ;
49
50
51
+ fn is_zero_const ( expr : & Expr < ' _ > , cx : & LateContext < ' _ > ) -> bool {
52
+ if let Some ( value) = constant_simple ( cx, cx. typeck_results ( ) , expr) {
53
+ return Constant :: Int ( 0 ) == value;
54
+ }
55
+ false
56
+ }
57
+
50
58
impl LateLintPass < ' _ > for IfNotElse {
51
59
fn check_expr ( & mut self , cx : & LateContext < ' _ > , item : & Expr < ' _ > ) {
52
60
// While loops will be desugared to ExprKind::If. This will cause the lint to fire.
@@ -72,7 +80,9 @@ impl LateLintPass<'_> for IfNotElse {
72
80
"remove the `!` and swap the blocks of the `if`/`else`" ,
73
81
) ;
74
82
} ,
75
- ExprKind :: Binary ( ref kind, _, _) if kind. node == BinOpKind :: Ne => {
83
+ ExprKind :: Binary ( ref kind, _, lhs) if kind. node == BinOpKind :: Ne && !is_zero_const ( lhs, cx) => {
84
+ // Disable firing the lint on `… != 0`, as these are likely to be bit tests.
85
+ // For example, `if foo & 0x0F00 != 0 { … } else { … }` already is in the "proper" order.
76
86
span_lint_and_help (
77
87
cx,
78
88
IF_NOT_ELSE ,
0 commit comments