@@ -45,8 +45,9 @@ declare_clippy_lint! {
4545 "if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`"
4646}
4747
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.
5051///
5152/// **Why is this bad?** Unnecessary code.
5253///
@@ -143,22 +144,54 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
143144 }
144145
145146 if let ExprKind :: Binary ( Spanned { node, .. } , ..) = e. node {
147+ let ignore_case = None :: < ( fn ( _) -> _ , & str ) > ;
148+ let ignore_no_literal = None :: < ( fn ( _, _) -> _ , & str ) > ;
146149 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 (
148167 cx,
149168 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+ ) ) ,
154180 ) ,
155- BinOpKind :: Ne => check_comparison (
181+ BinOpKind :: Gt => check_comparison (
156182 cx,
157183 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+ ) ) ,
162195 ) ,
163196 _ => ( ) ,
164197 }
@@ -169,22 +202,45 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
169202fn check_comparison < ' a , ' tcx > (
170203 cx : & LateContext < ' a , ' tcx > ,
171204 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 ) > ,
176210) {
177211 use self :: Expression :: * ;
178212
179213 if let ExprKind :: Binary ( _, ref left_side, ref right_side) = e. node {
180- let applicability = Applicability :: MachineApplicable ;
214+ let mut applicability = Applicability :: MachineApplicable ;
181215 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+ } ) ,
188244 _ => ( ) ,
189245 }
190246 }
@@ -196,7 +252,7 @@ fn suggest_bool_comparison<'a, 'tcx>(
196252 expr : & Expr ,
197253 mut applicability : Applicability ,
198254 message : & str ,
199- conv_hint : impl FnOnce ( Sugg < ' _ > ) -> Sugg < ' _ > ,
255+ conv_hint : impl FnOnce ( Sugg < ' a > ) -> Sugg < ' a > ,
200256) {
201257 let hint = Sugg :: hir_with_applicability ( cx, expr, ".." , & mut applicability) ;
202258 span_lint_and_sugg (
0 commit comments