about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/bool_to_int_with_if.rs27
-rw-r--r--tests/ui/bool_to_int_with_if.fixed24
-rw-r--r--tests/ui/bool_to_int_with_if.rs24
-rw-r--r--tests/ui/bool_to_int_with_if.stderr18
4 files changed, 83 insertions, 10 deletions
diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs
index 876ceef8c32..129e7747840 100644
--- a/clippy_lints/src/bool_to_int_with_if.rs
+++ b/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::HasSession;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{is_else_clause, is_in_const_context};
+use clippy_utils::{higher, is_else_clause, is_in_const_context, span_contains_comment};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -46,18 +47,25 @@ declare_lint_pass!(BoolToIntWithIf => [BOOL_TO_INT_WITH_IF]);
 
 impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::If(cond, then, Some(else_)) = expr.kind
-            && matches!(cond.kind, ExprKind::DropTemps(_))
+        if !expr.span.from_expansion()
+            && let Some(higher::If {
+                cond,
+                then,
+                r#else: Some(r#else),
+            }) = higher::If::hir(expr)
             && let Some(then_lit) = as_int_bool_lit(then)
-            && let Some(else_lit) = as_int_bool_lit(else_)
+            && let Some(else_lit) = as_int_bool_lit(r#else)
             && then_lit != else_lit
-            && !expr.span.from_expansion()
             && !is_in_const_context(cx)
         {
             let ty = cx.typeck_results().expr_ty(then);
-            let mut applicability = Applicability::MachineApplicable;
+            let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+                Applicability::MaybeIncorrect
+            } else {
+                Applicability::MachineApplicable
+            };
             let snippet = {
-                let mut sugg = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
+                let mut sugg = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "..", &mut applicability);
                 if !then_lit {
                     sugg = !sugg;
                 }
@@ -91,10 +99,11 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
     }
 }
 
-fn as_int_bool_lit(e: &Expr<'_>) -> Option<bool> {
-    if let ExprKind::Block(b, _) = e.kind
+fn as_int_bool_lit(expr: &Expr<'_>) -> Option<bool> {
+    if let ExprKind::Block(b, _) = expr.kind
         && b.stmts.is_empty()
         && let Some(e) = b.expr
+        && !e.span.from_expansion()
         && let ExprKind::Lit(lit) = e.kind
         && let LitKind::Int(x, _) = lit.node
     {
diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed
index 0080801d46b..ed6141244b4 100644
--- a/tests/ui/bool_to_int_with_if.fixed
+++ b/tests/ui/bool_to_int_with_if.fixed
@@ -117,3 +117,27 @@ fn if_let(a: Enum, b: Enum) {
         0
     };
 }
+
+fn issue14628() {
+    macro_rules! mac {
+        (if $cond:expr, $then:expr, $else:expr) => {
+            if $cond { $then } else { $else }
+        };
+        (zero) => {
+            0
+        };
+        (one) => {
+            1
+        };
+    }
+
+    let _ = i32::from(dbg!(4 > 0));
+    //~^ bool_to_int_with_if
+
+    let _ = dbg!(i32::from(4 > 0));
+    //~^ bool_to_int_with_if
+
+    let _ = mac!(if 4 > 0, 1, 0);
+    let _ = if 4 > 0 { mac!(one) } else { 0 };
+    let _ = if 4 > 0 { 1 } else { mac!(zero) };
+}
diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs
index 72c7e2c71c5..3f1f1c766e4 100644
--- a/tests/ui/bool_to_int_with_if.rs
+++ b/tests/ui/bool_to_int_with_if.rs
@@ -157,3 +157,27 @@ fn if_let(a: Enum, b: Enum) {
         0
     };
 }
+
+fn issue14628() {
+    macro_rules! mac {
+        (if $cond:expr, $then:expr, $else:expr) => {
+            if $cond { $then } else { $else }
+        };
+        (zero) => {
+            0
+        };
+        (one) => {
+            1
+        };
+    }
+
+    let _ = if dbg!(4 > 0) { 1 } else { 0 };
+    //~^ bool_to_int_with_if
+
+    let _ = dbg!(if 4 > 0 { 1 } else { 0 });
+    //~^ bool_to_int_with_if
+
+    let _ = mac!(if 4 > 0, 1, 0);
+    let _ = if 4 > 0 { mac!(one) } else { 0 };
+    let _ = if 4 > 0 { 1 } else { mac!(zero) };
+}
diff --git a/tests/ui/bool_to_int_with_if.stderr b/tests/ui/bool_to_int_with_if.stderr
index 415e80f8d73..94089bc6dc8 100644
--- a/tests/ui/bool_to_int_with_if.stderr
+++ b/tests/ui/bool_to_int_with_if.stderr
@@ -114,5 +114,21 @@ LL |     if a { 1 } else { 0 }
    |
    = note: `a as u8` or `a.into()` can also be valid options
 
-error: aborting due to 9 previous errors
+error: boolean to int conversion using if
+  --> tests/ui/bool_to_int_with_if.rs:174:13
+   |
+LL |     let _ = if dbg!(4 > 0) { 1 } else { 0 };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `i32::from(dbg!(4 > 0))`
+   |
+   = note: `dbg!(4 > 0) as i32` or `dbg!(4 > 0).into()` can also be valid options
+
+error: boolean to int conversion using if
+  --> tests/ui/bool_to_int_with_if.rs:177:18
+   |
+LL |     let _ = dbg!(if 4 > 0 { 1 } else { 0 });
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `i32::from(4 > 0)`
+   |
+   = note: `(4 > 0) as i32` or `(4 > 0).into()` can also be valid options
+
+error: aborting due to 11 previous errors