11use  clippy_utils:: diagnostics:: { span_lint_and_sugg,  span_lint_hir_and_then} ; 
22use  clippy_utils:: eq_expr_value; 
33use  clippy_utils:: source:: SpanRangeExt ; 
4+ use  clippy_utils:: sugg:: { make_binop,  Sugg } ; 
45use  clippy_utils:: ty:: { implements_trait,  is_type_diagnostic_item} ; 
56use  rustc_ast:: ast:: LitKind ; 
67use  rustc_errors:: Applicability ; 
@@ -83,7 +84,11 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
8384        _:  Span , 
8485        _:  LocalDefId , 
8586    )  { 
86-         NonminimalBoolVisitor  {  cx } . visit_body ( body) ; 
87+         NonminimalBoolVisitor  { 
88+             cx, 
89+             parent_expr :  vec ! [ ] , 
90+         } 
91+         . visit_body ( body) ; 
8792    } 
8893
8994    fn  check_expr ( & mut  self ,  cx :  & LateContext < ' tcx > ,  expr :  & ' tcx  Expr < ' tcx > )  { 
@@ -176,13 +181,65 @@ fn check_inverted_bool_in_condition(
176181    ) ; 
177182} 
178183
179- fn  check_simplify_not ( cx :  & LateContext < ' _ > ,  expr :  & Expr < ' _ > )  { 
184+ fn  check_simplify_not ( cx :  & LateContext < ' _ > ,  expr :  & Expr < ' _ > ,   parent_expr :   Option < & Expr < ' _ > > )  { 
180185    if  let  ExprKind :: Unary ( UnOp :: Not ,  inner)  = & expr. kind 
181186        && !expr. span . from_expansion ( ) 
182187        && !inner. span . from_expansion ( ) 
183188        && let  Some ( suggestion)  = simplify_not ( cx,  inner) 
184189        && cx. tcx . lint_level_at_node ( NONMINIMAL_BOOL ,  expr. hir_id ) . 0  != Level :: Allow 
185190    { 
191+         let  need_parens = ' block:  { 
192+             let  Some ( parent_expr)  = parent_expr else  { 
193+                 break  ' block false ; 
194+             } ; 
195+             match  parent_expr. kind  { 
196+                 ExprKind :: Cast ( _,  ty)  => { 
197+                     let  new_expr = Expr  { 
198+                         kind :  ExprKind :: Cast ( inner,  ty) , 
199+                         ..* parent_expr
200+                     } ; 
201+                     let  Some ( new_sugg)  = Sugg :: hir_opt ( cx,  & new_expr)  else  { 
202+                         break  ' block false ; 
203+                     } ; 
204+                     let  Sugg :: BinOp ( _,  lhs,  _)  = new_sugg else  { 
205+                         break  ' block false ; 
206+                     } ; 
207+                     lhs. starts_with ( '(' )  && lhs. ends_with ( ')' ) 
208+                 } , 
209+                 ExprKind :: Binary ( binop,  lhs,  rhs)  if  lhs. span  == expr. span  => { 
210+                     let  Some ( lhs_sugg)  = Sugg :: hir_opt ( cx,  inner)  else  { 
211+                         break  ' block false ; 
212+                     } ; 
213+                     let  Some ( rhs_sugg)  = Sugg :: hir_opt ( cx,  rhs)  else  { 
214+                         break  ' block false ; 
215+                     } ; 
216+                     let  new_sugg = make_binop ( binop. node ,  & lhs_sugg,  & rhs_sugg) ; 
217+                     let  Sugg :: BinOp ( _,  lhs,  _)  = new_sugg else  { 
218+                         break  ' block false ; 
219+                     } ; 
220+                     lhs. starts_with ( '(' )  && lhs. ends_with ( ')' ) 
221+                 } , 
222+                 ExprKind :: Binary ( binop,  lhs,  rhs)  if  rhs. span  == expr. span  => { 
223+                     let  Some ( lhs_sugg)  = Sugg :: hir_opt ( cx,  lhs)  else  { 
224+                         break  ' block false ; 
225+                     } ; 
226+                     let  Some ( rhs_sugg)  = Sugg :: hir_opt ( cx,  inner)  else  { 
227+                         break  ' block false ; 
228+                     } ; 
229+                     let  new_sugg = make_binop ( binop. node ,  & lhs_sugg,  & rhs_sugg) ; 
230+                     let  Sugg :: BinOp ( _,  _,  rhs)  = new_sugg else  { 
231+                         break  ' block false ; 
232+                     } ; 
233+                     rhs. starts_with ( '(' )  && rhs. ends_with ( ')' ) 
234+                 } , 
235+                 _ => false , 
236+             } 
237+         } ; 
238+         let  suggestion = if  need_parens { 
239+             format ! ( "({suggestion})" ) 
240+         }  else  { 
241+             suggestion
242+         } ; 
186243        span_lint_and_sugg ( 
187244            cx, 
188245            NONMINIMAL_BOOL , 
@@ -196,6 +253,7 @@ fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) {
196253} 
197254
198255struct  NonminimalBoolVisitor < ' a ,  ' tcx >  { 
256+     parent_expr :  Vec < & ' tcx  Expr < ' tcx > > ,  // parent stack 
199257    cx :  & ' a  LateContext < ' tcx > , 
200258} 
201259
@@ -569,7 +627,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
569627                } 
570628            } ; 
571629            if  improvements. is_empty ( )  { 
572-                 check_simplify_not ( self . cx ,  e) ; 
630+                 check_simplify_not ( self . cx ,  e,   self . parent_expr . last ( ) . copied ( ) ) ; 
573631            }  else  { 
574632                nonminimal_bool_lint ( 
575633                    improvements
@@ -602,7 +660,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
602660                _ => { } , 
603661            } 
604662        } 
663+         self . parent_expr . push ( e) ; 
605664        walk_expr ( self ,  e) ; 
665+         self . parent_expr . pop ( ) ; 
606666    } 
607667} 
608668
0 commit comments