1
1
use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
2
use clippy_utils:: source:: snippet_with_applicability;
3
+ use rustc_ast:: ast:: BinOpKind :: { Add , BitAnd , BitOr , BitXor , Div , Mul , Rem , Shl , Shr , Sub } ;
3
4
use rustc_ast:: ast:: { BinOpKind , Expr , ExprKind } ;
4
5
use rustc_errors:: Applicability ;
5
6
use rustc_lint:: { EarlyContext , EarlyLintPass } ;
@@ -12,6 +13,7 @@ declare_clippy_lint! {
12
13
/// and suggests to add parentheses. Currently it catches the following:
13
14
/// * mixed usage of arithmetic and bit shifting/combining operators without
14
15
/// parentheses
16
+ /// * mixed usage of bitmasking and bit shifting operators without parentheses
15
17
///
16
18
/// ### Why is this bad?
17
19
/// Not everyone knows the precedence of those operators by
@@ -20,6 +22,7 @@ declare_clippy_lint! {
20
22
///
21
23
/// ### Example
22
24
/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
25
+ /// * `0x2345 & 0xF000 >> 12` equals 5, while `(0x2345 & 0xF000) >> 12` equals 2
23
26
#[ clippy:: version = "pre 1.29.0" ]
24
27
pub PRECEDENCE ,
25
28
complexity,
@@ -51,8 +54,13 @@ impl EarlyLintPass for Precedence {
51
54
return ;
52
55
}
53
56
let mut applicability = Applicability :: MachineApplicable ;
54
- match ( is_arith_expr ( left) , is_arith_expr ( right) ) {
55
- ( true , true ) => {
57
+ match ( op, get_bin_opt ( left) , get_bin_opt ( right) ) {
58
+ (
59
+ BitAnd | BitOr | BitXor ,
60
+ Some ( Shl | Shr | Add | Div | Mul | Rem | Sub ) ,
61
+ Some ( Shl | Shr | Add | Div | Mul | Rem | Sub ) ,
62
+ )
63
+ | ( Shl | Shr , Some ( Add | Div | Mul | Rem | Sub ) , Some ( Add | Div | Mul | Rem | Sub ) ) => {
56
64
let sugg = format ! (
57
65
"({}) {} ({})" ,
58
66
snippet_with_applicability( cx, left. span, ".." , & mut applicability) ,
@@ -61,7 +69,8 @@ impl EarlyLintPass for Precedence {
61
69
) ;
62
70
span_sugg ( expr, sugg, applicability) ;
63
71
} ,
64
- ( true , false ) => {
72
+ ( BitAnd | BitOr | BitXor , Some ( Shl | Shr | Add | Div | Mul | Rem | Sub ) , _)
73
+ | ( Shl | Shr , Some ( Add | Div | Mul | Rem | Sub ) , _) => {
65
74
let sugg = format ! (
66
75
"({}) {} {}" ,
67
76
snippet_with_applicability( cx, left. span, ".." , & mut applicability) ,
@@ -70,7 +79,8 @@ impl EarlyLintPass for Precedence {
70
79
) ;
71
80
span_sugg ( expr, sugg, applicability) ;
72
81
} ,
73
- ( false , true ) => {
82
+ ( BitAnd | BitOr | BitXor , _, Some ( Shl | Shr | Add | Div | Mul | Rem | Sub ) )
83
+ | ( Shl | Shr , _, Some ( Add | Div | Mul | Rem | Sub ) ) => {
74
84
let sugg = format ! (
75
85
"{} {} ({})" ,
76
86
snippet_with_applicability( cx, left. span, ".." , & mut applicability) ,
@@ -79,27 +89,20 @@ impl EarlyLintPass for Precedence {
79
89
) ;
80
90
span_sugg ( expr, sugg, applicability) ;
81
91
} ,
82
- ( false , false ) => ( ) ,
92
+ _ => ( ) ,
83
93
}
84
94
}
85
95
}
86
96
}
87
97
88
- fn is_arith_expr ( expr : & Expr ) -> bool {
98
+ fn get_bin_opt ( expr : & Expr ) -> Option < BinOpKind > {
89
99
match expr. kind {
90
- ExprKind :: Binary ( Spanned { node : op, .. } , _, _) => is_arith_op ( op) ,
91
- _ => false ,
100
+ ExprKind :: Binary ( Spanned { node : op, .. } , _, _) => Some ( op) ,
101
+ _ => None ,
92
102
}
93
103
}
94
104
95
105
#[ must_use]
96
106
fn is_bit_op ( op : BinOpKind ) -> bool {
97
- use rustc_ast:: ast:: BinOpKind :: { BitAnd , BitOr , BitXor , Shl , Shr } ;
98
107
matches ! ( op, BitXor | BitAnd | BitOr | Shl | Shr )
99
108
}
100
-
101
- #[ must_use]
102
- fn is_arith_op ( op : BinOpKind ) -> bool {
103
- use rustc_ast:: ast:: BinOpKind :: { Add , Div , Mul , Rem , Sub } ;
104
- matches ! ( op, Add | Sub | Mul | Div | Rem )
105
- }
0 commit comments