]> git.lizzy.rs Git - rust.git/commitdiff
Add erasing_op lint
authorYury Krivopalov <ykrivopalov@yandex.ru>
Sat, 30 Sep 2017 17:14:00 +0000 (20:14 +0300)
committerYury Krivopalov <ykrivopalov@yandex.ru>
Sat, 14 Oct 2017 09:34:37 +0000 (12:34 +0300)
For expressions that can be replaced by a zero.

clippy_lints/src/erasing_op.rs [new file with mode: 0644]
clippy_lints/src/lib.rs
tests/ui/bit_masks.stderr
tests/ui/erasing_op.rs [new file with mode: 0644]
tests/ui/erasing_op.stderr [new file with mode: 0644]

diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs
new file mode 100644 (file)
index 0000000..7b5b4a3
--- /dev/null
@@ -0,0 +1,62 @@
+use consts::{constant_simple, Constant};
+use rustc::hir::*;
+use rustc::lint::*;
+use syntax::codemap::Span;
+use utils::{in_macro, span_lint};
+
+/// **What it does:** Checks for erasing operations, e.g. `x * 0`.
+///
+/// **Why is this bad?** The whole expression can be replaced by zero.
+/// Most likely mistake was made and code should be reviewed or simplified.
+///
+/// **Known problems:** None.
+///
+/// **Example:**
+/// ```rust
+/// 0 / x; 0 * x; x & 0
+/// ```
+declare_lint! {
+    pub ERASING_OP,
+    Warn,
+    "using erasing operations, e.g. `x * 0` or `y & 0`"
+}
+
+#[derive(Copy, Clone)]
+pub struct ErasingOp;
+
+impl LintPass for ErasingOp {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(ERASING_OP)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp {
+    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
+        if in_macro(e.span) {
+            return;
+        }
+        if let ExprBinary(ref cmp, ref left, ref right) = e.node {
+            match cmp.node {
+                BiMul | BiBitAnd => {
+                    check(cx, left, e.span);
+                    check(cx, right, e.span);
+                },
+                BiDiv => check(cx, left, e.span),
+                _ => (),
+            }
+        }
+    }
+}
+
+fn check(cx: &LateContext, e: &Expr, span: Span) {
+    if let Some(Constant::Int(v)) = constant_simple(cx, e) {
+        if v.to_u128_unchecked() == 0 {
+            span_lint(
+                cx,
+                ERASING_OP,
+                span,
+                "the operation is ineffective. Consider reducing it to `0`",
+            );
+        }
+    }
+}
index 0f27a74ac8e3f97174d0e4e9aa6d443a2ff216dc..6c85b9efa55c2e70b180f584b6fa5a4b7d834e12 100644 (file)
@@ -86,6 +86,7 @@ macro_rules! declare_restriction_lint {
 pub mod enum_clike;
 pub mod enum_glob_use;
 pub mod enum_variants;
+pub mod erasing_op;
 pub mod eq_op;
 pub mod escape;
 pub mod eta_reduction;
@@ -246,6 +247,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
     reg.register_early_lint_pass(box needless_continue::NeedlessContinue);
     reg.register_late_lint_pass(box eta_reduction::EtaPass);
     reg.register_late_lint_pass(box identity_op::IdentityOp);
+    reg.register_late_lint_pass(box erasing_op::ErasingOp);
     reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements);
     reg.register_late_lint_pass(box mut_mut::MutMut);
     reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed);
index 9f2c2d0a2c4aaeb65975b4994c9b160f63d25c39..45b8bbe6d9e4b28f30824adcc11d5b5238fccd8c 100644 (file)
@@ -6,6 +6,14 @@ error: &-masking with zero
    |
    = note: `-D bad-bit-mask` implied by `-D warnings`
 
+error: the operation is ineffective. Consider reducing it to `0`
+  --> $DIR/bit_masks.rs:12:5
+   |
+12 |     x & 0 == 0;
+   |     ^^^^^
+   |
+   = note: `-D erasing-op` implied by `-D warnings`
+
 error: incompatible bit mask: `_ & 2` can never be equal to `1`
   --> $DIR/bit_masks.rs:15:5
    |
@@ -48,6 +56,12 @@ error: &-masking with zero
 35 |     0 & x == 0;
    |     ^^^^^^^^^^
 
+error: the operation is ineffective. Consider reducing it to `0`
+  --> $DIR/bit_masks.rs:35:5
+   |
+35 |     0 & x == 0;
+   |     ^^^^^
+
 error: incompatible bit mask: `_ | 2` will always be higher than `1`
   --> $DIR/bit_masks.rs:39:5
    |
diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs
new file mode 100644 (file)
index 0000000..e514314
--- /dev/null
@@ -0,0 +1,12 @@
+
+
+
+#[allow(no_effect)]
+#[warn(erasing_op)]
+fn main() {
+    let x: u8 = 0;
+
+    x * 0;
+    0 & x;
+    0 / x;
+}
diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr
new file mode 100644 (file)
index 0000000..496c297
--- /dev/null
@@ -0,0 +1,20 @@
+error: the operation is ineffective. Consider reducing it to `0`
+ --> $DIR/erasing_op.rs:9:5
+  |
+9 |     x * 0;
+  |     ^^^^^
+  |
+  = note: `-D erasing-op` implied by `-D warnings`
+
+error: the operation is ineffective. Consider reducing it to `0`
+  --> $DIR/erasing_op.rs:10:5
+   |
+10 |     0 & x;
+   |     ^^^^^
+
+error: the operation is ineffective. Consider reducing it to `0`
+  --> $DIR/erasing_op.rs:11:5
+   |
+11 |     0 / x;
+   |     ^^^^^
+