Skip to content

Commit bc63bd2

Browse files
fix incorrect suggestion for !(a >= b) as i32 == c
1 parent a81f1c8 commit bc63bd2

File tree

4 files changed

+86
-4
lines changed

4 files changed

+86
-4
lines changed

clippy_lints/src/booleans.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
8383
_: Span,
8484
_: LocalDefId,
8585
) {
86-
NonminimalBoolVisitor { cx }.visit_body(body);
86+
NonminimalBoolVisitor {
87+
cx,
88+
parent_expr: vec![],
89+
}
90+
.visit_body(body);
8791
}
8892

8993
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -176,13 +180,28 @@ fn check_inverted_bool_in_condition(
176180
);
177181
}
178182

179-
fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) {
183+
fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>, parent_expr: Option<&Expr<'_>>) {
180184
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind
181185
&& !expr.span.from_expansion()
182186
&& !inner.span.from_expansion()
183187
&& let Some(suggestion) = simplify_not(cx, inner)
184188
&& cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
185189
{
190+
let need_parens = 'block: {
191+
if matches!(inner.kind, ExprKind::Binary(..)) {
192+
if let Some(parent_expr) = parent_expr {
193+
if matches!(parent_expr.kind, ExprKind::Cast(..) | ExprKind::Binary(..)) {
194+
break 'block true;
195+
}
196+
}
197+
}
198+
false
199+
};
200+
let suggestion = if need_parens {
201+
format!("({suggestion})")
202+
} else {
203+
suggestion
204+
};
186205
span_lint_and_sugg(
187206
cx,
188207
NONMINIMAL_BOOL,
@@ -196,6 +215,7 @@ fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) {
196215
}
197216

198217
struct NonminimalBoolVisitor<'a, 'tcx> {
218+
parent_expr: Vec<&'tcx Expr<'tcx>>, // parent stack
199219
cx: &'a LateContext<'tcx>,
200220
}
201221

@@ -569,7 +589,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
569589
}
570590
};
571591
if improvements.is_empty() {
572-
check_simplify_not(self.cx, e);
592+
check_simplify_not(self.cx, e, self.parent_expr.last().copied());
573593
} else {
574594
nonminimal_bool_lint(
575595
improvements
@@ -602,7 +622,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
602622
_ => {},
603623
}
604624
}
625+
self.parent_expr.push(e);
605626
walk_expr(self, e);
627+
self.parent_expr.pop();
606628
}
607629
}
608630

tests/ui/nonminimal_bool_methods.fixed

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,16 @@ fn issue_12625() {
115115
if a as u64 > b {} //~ ERROR: this boolean expression can be simplified
116116
}
117117

118+
fn issue_12761() {
119+
let a = 0;
120+
let b = 0;
121+
let c = 0;
122+
if (a < b) as i32 == c {} //~ ERROR: this boolean expression can be simplified
123+
if (a < b) | (a > c) {} //~ ERROR: this boolean expression can be simplified
124+
let opt: Option<usize> = Some(1);
125+
let res: Result<usize, usize> = Ok(1);
126+
if res.is_err() as i32 == c {} //~ ERROR: this boolean expression can be simplified
127+
if res.is_err() | opt.is_some() {} //~ ERROR: this boolean expression can be simplified
128+
}
129+
118130
fn main() {}

tests/ui/nonminimal_bool_methods.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,16 @@ fn issue_12625() {
115115
if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified
116116
}
117117

118+
fn issue_12761() {
119+
let a = 0;
120+
let b = 0;
121+
let c = 0;
122+
if !(a >= b) as i32 == c {} //~ ERROR: this boolean expression can be simplified
123+
if !(a >= b) | !(a <= c) {} //~ ERROR: this boolean expression can be simplified
124+
let opt: Option<usize> = Some(1);
125+
let res: Result<usize, usize> = Ok(1);
126+
if !res.is_ok() as i32 == c {} //~ ERROR: this boolean expression can be simplified
127+
if !res.is_ok() | !opt.is_none() {} //~ ERROR: this boolean expression can be simplified
128+
}
129+
118130
fn main() {}

tests/ui/nonminimal_bool_methods.stderr

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,41 @@ error: this boolean expression can be simplified
9797
LL | if !(a as u64 <= b) {}
9898
| ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b`
9999

100-
error: aborting due to 16 previous errors
100+
error: this boolean expression can be simplified
101+
--> tests/ui/nonminimal_bool_methods.rs:122:8
102+
|
103+
LL | if !(a >= b) as i32 == c {}
104+
| ^^^^^^^^^ help: try: `(a < b)`
105+
106+
error: this boolean expression can be simplified
107+
--> tests/ui/nonminimal_bool_methods.rs:123:8
108+
|
109+
LL | if !(a >= b) | !(a <= c) {}
110+
| ^^^^^^^^^ help: try: `(a < b)`
111+
112+
error: this boolean expression can be simplified
113+
--> tests/ui/nonminimal_bool_methods.rs:123:20
114+
|
115+
LL | if !(a >= b) | !(a <= c) {}
116+
| ^^^^^^^^^ help: try: `(a > c)`
117+
118+
error: this boolean expression can be simplified
119+
--> tests/ui/nonminimal_bool_methods.rs:126:8
120+
|
121+
LL | if !res.is_ok() as i32 == c {}
122+
| ^^^^^^^^^^^^ help: try: `res.is_err()`
123+
124+
error: this boolean expression can be simplified
125+
--> tests/ui/nonminimal_bool_methods.rs:127:8
126+
|
127+
LL | if !res.is_ok() | !opt.is_none() {}
128+
| ^^^^^^^^^^^^ help: try: `res.is_err()`
129+
130+
error: this boolean expression can be simplified
131+
--> tests/ui/nonminimal_bool_methods.rs:127:23
132+
|
133+
LL | if !res.is_ok() | !opt.is_none() {}
134+
| ^^^^^^^^^^^^^^ help: try: `opt.is_some()`
135+
136+
error: aborting due to 22 previous errors
101137

0 commit comments

Comments
 (0)