@@ -45,8 +45,9 @@ declare_clippy_lint! {
45
45
"if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`"
46
46
}
47
47
48
- /// **What it does:** Checks for expressions of the form `x == true` and
49
- /// `x != true` (or vice versa) and suggest using the variable directly.
48
+ /// **What it does:** Checks for expressions of the form `x == true`,
49
+ /// `x != true` and order comparisons such as `x < true` (or vice versa) and
50
+ /// suggest using the variable directly.
50
51
///
51
52
/// **Why is this bad?** Unnecessary code.
52
53
///
@@ -143,22 +144,54 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
143
144
}
144
145
145
146
if let ExprKind :: Binary ( Spanned { node, .. } , ..) = e. node {
147
+ let ignore_case = None :: < ( fn ( _) -> _ , & str ) > ;
148
+ let ignore_no_literal = None :: < ( fn ( _, _) -> _ , & str ) > ;
146
149
match node {
147
- BinOpKind :: Eq => check_comparison (
150
+ BinOpKind :: Eq => {
151
+ let true_case = Some ( ( |h| h, "equality checks against true are unnecessary" ) ) ;
152
+ let false_case = Some ( (
153
+ |h : Sugg < ' _ > | !h,
154
+ "equality checks against false can be replaced by a negation" ,
155
+ ) ) ;
156
+ check_comparison ( cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
157
+ } ,
158
+ BinOpKind :: Ne => {
159
+ let true_case = Some ( (
160
+ |h : Sugg < ' _ > | !h,
161
+ "inequality checks against true can be replaced by a negation" ,
162
+ ) ) ;
163
+ let false_case = Some ( ( |h| h, "inequality checks against false are unnecessary" ) ) ;
164
+ check_comparison ( cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
165
+ } ,
166
+ BinOpKind :: Lt => check_comparison (
148
167
cx,
149
168
e,
150
- "equality checks against true are unnecessary" ,
151
- "equality checks against false can be replaced by a negation" ,
152
- |h| h,
153
- |h| !h,
169
+ ignore_case,
170
+ Some ( ( |h| h, "greater than checks against false are unnecessary" ) ) ,
171
+ Some ( (
172
+ |h : Sugg < ' _ > | !h,
173
+ "less than comparison against true can be replaced by a negation" ,
174
+ ) ) ,
175
+ ignore_case,
176
+ Some ( (
177
+ |l : Sugg < ' _ > , r : Sugg < ' _ > | ( !l) . bit_and ( & r) ,
178
+ "order comparisons between booleans can be simplified" ,
179
+ ) ) ,
154
180
) ,
155
- BinOpKind :: Ne => check_comparison (
181
+ BinOpKind :: Gt => check_comparison (
156
182
cx,
157
183
e,
158
- "inequality checks against true can be replaced by a negation" ,
159
- "inequality checks against false are unnecessary" ,
160
- |h| !h,
161
- |h| h,
184
+ Some ( (
185
+ |h : Sugg < ' _ > | !h,
186
+ "less than comparison against true can be replaced by a negation" ,
187
+ ) ) ,
188
+ ignore_case,
189
+ ignore_case,
190
+ Some ( ( |h| h, "greater than checks against false are unnecessary" ) ) ,
191
+ Some ( (
192
+ |l : Sugg < ' _ > , r : Sugg < ' _ > | l. bit_and ( & ( !r) ) ,
193
+ "order comparisons between booleans can be simplified" ,
194
+ ) ) ,
162
195
) ,
163
196
_ => ( ) ,
164
197
}
@@ -169,22 +202,45 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
169
202
fn check_comparison < ' a , ' tcx > (
170
203
cx : & LateContext < ' a , ' tcx > ,
171
204
e : & ' tcx Expr ,
172
- true_message : & str ,
173
- false_message : & str ,
174
- true_hint : impl FnOnce ( Sugg < ' _ > ) -> Sugg < ' _ > ,
175
- false_hint : impl FnOnce ( Sugg < ' _ > ) -> Sugg < ' _ > ,
205
+ left_true : Option < ( impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > , & str ) > ,
206
+ left_false : Option < ( impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > , & str ) > ,
207
+ right_true : Option < ( impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > , & str ) > ,
208
+ right_false : Option < ( impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > , & str ) > ,
209
+ no_literal : Option < ( impl FnOnce ( Sugg < ' a > , Sugg < ' a > ) -> Sugg < ' a > , & str ) > ,
176
210
) {
177
211
use self :: Expression :: * ;
178
212
179
213
if let ExprKind :: Binary ( _, ref left_side, ref right_side) = e. node {
180
- let applicability = Applicability :: MachineApplicable ;
214
+ let mut applicability = Applicability :: MachineApplicable ;
181
215
match ( fetch_bool_expr ( left_side) , fetch_bool_expr ( right_side) ) {
182
- ( Bool ( true ) , Other ) => suggest_bool_comparison ( cx, e, right_side, applicability, true_message, true_hint) ,
183
- ( Other , Bool ( true ) ) => suggest_bool_comparison ( cx, e, left_side, applicability, true_message, true_hint) ,
184
- ( Bool ( false ) , Other ) => {
185
- suggest_bool_comparison ( cx, e, right_side, applicability, false_message, false_hint)
186
- } ,
187
- ( Other , Bool ( false ) ) => suggest_bool_comparison ( cx, e, left_side, applicability, false_message, false_hint) ,
216
+ ( Bool ( true ) , Other ) => left_true. map_or ( ( ) , |( h, m) | {
217
+ suggest_bool_comparison ( cx, e, right_side, applicability, m, h)
218
+ } ) ,
219
+ ( Other , Bool ( true ) ) => right_true. map_or ( ( ) , |( h, m) | {
220
+ suggest_bool_comparison ( cx, e, left_side, applicability, m, h)
221
+ } ) ,
222
+ ( Bool ( false ) , Other ) => left_false. map_or ( ( ) , |( h, m) | {
223
+ suggest_bool_comparison ( cx, e, right_side, applicability, m, h)
224
+ } ) ,
225
+ ( Other , Bool ( false ) ) => right_false. map_or ( ( ) , |( h, m) | {
226
+ suggest_bool_comparison ( cx, e, left_side, applicability, m, h)
227
+ } ) ,
228
+ ( Other , Other ) => no_literal. map_or ( ( ) , |( h, m) | {
229
+ let ( l_ty, r_ty) = ( cx. tables . expr_ty ( left_side) , cx. tables . expr_ty ( right_side) ) ;
230
+ if l_ty. is_bool ( ) && r_ty. is_bool ( ) {
231
+ let left_side = Sugg :: hir_with_applicability ( cx, left_side, ".." , & mut applicability) ;
232
+ let right_side = Sugg :: hir_with_applicability ( cx, right_side, ".." , & mut applicability) ;
233
+ span_lint_and_sugg (
234
+ cx,
235
+ BOOL_COMPARISON ,
236
+ e. span ,
237
+ m,
238
+ "try simplifying it as shown" ,
239
+ h ( left_side, right_side) . to_string ( ) ,
240
+ applicability,
241
+ )
242
+ }
243
+ } ) ,
188
244
_ => ( ) ,
189
245
}
190
246
}
@@ -196,7 +252,7 @@ fn suggest_bool_comparison<'a, 'tcx>(
196
252
expr : & Expr ,
197
253
mut applicability : Applicability ,
198
254
message : & str ,
199
- conv_hint : impl FnOnce ( Sugg < ' _ > ) -> Sugg < ' _ > ,
255
+ conv_hint : impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > ,
200
256
) {
201
257
let hint = Sugg :: hir_with_applicability ( cx, expr, ".." , & mut applicability) ;
202
258
span_lint_and_sugg (
0 commit comments