diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs index a4b8cbb0d82..bea74279e03 100644 --- a/clippy_lints/src/bool_to_int_with_if.rs +++ b/clippy_lints/src/bool_to_int_with_if.rs @@ -55,15 +55,28 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx if let ExprKind::If(check, then, Some(else_)) = expr.kind && let Some(then_lit) = int_literal(then) && let Some(else_lit) = int_literal(else_) - && check_int_literal_equals_val(then_lit, 1) - && check_int_literal_equals_val(else_lit, 0) { + let inverted = if + check_int_literal_equals_val(then_lit, 1) + && check_int_literal_equals_val(else_lit, 0) { + false + } else if + check_int_literal_equals_val(then_lit, 0) + && check_int_literal_equals_val(else_lit, 1) { + true + } else { + // Expression isn't boolean, exit + return; + }; let mut applicability = Applicability::MachineApplicable; let snippet = snippet_block_with_applicability(ctx, check.span, "..", None, &mut applicability); + + let invert = if inverted { "!" } else { "" }; + let need_parens = should_have_parentheses(check); + let snippet_with_braces = { - let need_parens = should_have_parentheses(check); let (left_paren, right_paren) = if need_parens {("(", ")")} else {("", "")}; - format!("{left_paren}{snippet}{right_paren}") + format!("{invert}{left_paren}{snippet}{right_paren}") }; let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type @@ -71,11 +84,14 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx let suggestion = { let wrap_in_curly = is_else_clause(ctx.tcx, expr); let (left_curly, right_curly) = if wrap_in_curly {("{", "}")} else {("", "")}; + let (left_paren, right_paren) = if inverted && need_parens {("(", ")")} else {("", "")}; format!( - "{left_curly}{ty}::from({snippet}){right_curly}" + "{left_curly}{ty}::from({invert}{left_paren}{snippet}{right_paren}){right_curly}" ) }; // when used in else clause if statement should be wrapped in curly braces + let (inverted_left_paren, inverted_right_paren) = if inverted {("(", ")")} else {("", "")}; + span_lint_and_then(ctx, BOOL_TO_INT_WITH_IF, expr.span, @@ -87,7 +103,7 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx suggestion, applicability, ); - diag.note(format!("`{snippet_with_braces} as {ty}` or `{snippet_with_braces}.into()` can also be valid options")); + diag.note(format!("`{snippet_with_braces} as {ty}` or `{inverted_left_paren}{snippet_with_braces}{inverted_right_paren}.into()` can also be valid options")); }); }; } diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed index 9c1098dc4c1..c48dc941b84 100644 --- a/tests/ui/bool_to_int_with_if.fixed +++ b/tests/ui/bool_to_int_with_if.fixed @@ -14,6 +14,7 @@ fn main() { // precedence i32::from(a); i32::from(!a); + i32::from(!a); i32::from(a || b); i32::from(cond(a, b)); i32::from(x + y < 4); @@ -23,6 +24,11 @@ fn main() { 123 } else {i32::from(b)}; + // if else if inverted + if a { + 123 + } else {i32::from(!b)}; + // Shouldn't lint if a { diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs index 0c967dac6e2..5d9496f0177 100644 --- a/tests/ui/bool_to_int_with_if.rs +++ b/tests/ui/bool_to_int_with_if.rs @@ -17,6 +17,11 @@ fn main() { } else { 0 }; + if a { + 0 + } else { + 1 + }; if !a { 1 } else { @@ -47,6 +52,15 @@ fn main() { 0 }; + // if else if inverted + if a { + 123 + } else if b { + 0 + } else { + 1 + }; + // Shouldn't lint if a { diff --git a/tests/ui/bool_to_int_with_if.stderr b/tests/ui/bool_to_int_with_if.stderr index 8647a9cffbe..cc3e0395aa4 100644 --- a/tests/ui/bool_to_int_with_if.stderr +++ b/tests/ui/bool_to_int_with_if.stderr @@ -14,6 +14,18 @@ LL | | }; error: boolean to int conversion using if --> $DIR/bool_to_int_with_if.rs:20:5 | +LL | / if a { +LL | | 0 +LL | | } else { +LL | | 1 +LL | | }; + | |_____^ help: replace with from: `i32::from(!a)` + | + = note: `!a as i32` or `(!a).into()` can also be valid options + +error: boolean to int conversion using if + --> $DIR/bool_to_int_with_if.rs:25:5 + | LL | / if !a { LL | | 1 LL | | } else { @@ -24,7 +36,7 @@ LL | | }; = note: `!a as i32` or `!a.into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:25:5 + --> $DIR/bool_to_int_with_if.rs:30:5 | LL | / if a || b { LL | | 1 @@ -36,7 +48,7 @@ LL | | }; = note: `(a || b) as i32` or `(a || b).into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:30:5 + --> $DIR/bool_to_int_with_if.rs:35:5 | LL | / if cond(a, b) { LL | | 1 @@ -48,7 +60,7 @@ LL | | }; = note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:35:5 + --> $DIR/bool_to_int_with_if.rs:40:5 | LL | / if x + y < 4 { LL | | 1 @@ -60,7 +72,7 @@ LL | | }; = note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:44:12 + --> $DIR/bool_to_int_with_if.rs:49:12 | LL | } else if b { | ____________^ @@ -73,12 +85,25 @@ LL | | }; = note: `b as i32` or `b.into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:102:5 + --> $DIR/bool_to_int_with_if.rs:58:12 + | +LL | } else if b { + | ____________^ +LL | | 0 +LL | | } else { +LL | | 1 +LL | | }; + | |_____^ help: replace with from: `{i32::from(!b)}` + | + = note: `!b as i32` or `(!b).into()` can also be valid options + +error: boolean to int conversion using if + --> $DIR/bool_to_int_with_if.rs:116:5 | LL | if a { 1 } else { 0 } | ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)` | = note: `a as u8` or `a.into()` can also be valid options -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors