]> git.lizzy.rs Git - rust.git/commitdiff
Use the authoring tool to create a new lint
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Mon, 3 Jul 2017 14:07:04 +0000 (16:07 +0200)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Tue, 1 Aug 2017 10:55:52 +0000 (12:55 +0200)
clippy_lints/src/bit_mask.rs
clippy_lints/src/lib.rs
clippy_tests/examples/bit_masks.stderr
clippy_tests/examples/trailing_zeros.stderr
clippy_tests/examples/trailing_zeros.stdout

index c1fbd33b2a5ea48834c62c69c91c288566466c93..889f74d52e79a6211094631f3225a3dea86c94fd 100644 (file)
@@ -4,7 +4,8 @@
 use rustc_const_eval::lookup_const_by_id;
 use syntax::ast::LitKind;
 use syntax::codemap::Span;
-use utils::span_lint;
+use utils::{span_lint, span_lint_and_then};
+use utils::sugg::Sugg;
 
 /// **What it does:** Checks for incompatible bit masks in comparisons.
 ///
     "expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`"
 }
 
+/// **What it does:** Checks for bit masks that can be replaced by a call
+/// to `trailing_zeros`
+///
+/// **Why is this bad?** `x.trailing_zeros() > 4` is much clearer than `x & 15 == 0`
+///
+/// **Known problems:** None
+///
+/// **Example:**
+/// ```rust
+/// x & 0x1111 == 0
+/// ```
+declare_lint! {
+    pub VERBOSE_BIT_MASK,
+    Warn,
+    "expressions where a bit mask is less readable than the corresponding method call"
+}
+
 #[derive(Copy,Clone)]
 pub struct BitMask;
 
 impl LintPass for BitMask {
     fn get_lints(&self) -> LintArray {
-        lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK)
+        lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK)
     }
 }
 
@@ -90,6 +108,26 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
                 }
             }
         }
+        if_let_chain!{[
+            let Expr_::ExprBinary(ref op, ref left, ref right) = e.node,
+            BinOp_::BiEq == op.node,
+            let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node,
+            BinOp_::BiBitAnd == op1.node,
+            let Expr_::ExprLit(ref lit) = right1.node,
+            let LitKind::Int(n, _) = lit.node,
+            let Expr_::ExprLit(ref lit1) = right.node,
+            let LitKind::Int(0, _) = lit1.node,
+            n.leading_zeros() == n.count_zeros(),
+        ], {
+            span_lint_and_then(cx,
+                               VERBOSE_BIT_MASK,
+                               e.span,
+                               "bit mask could be simplified with a call to `trailing_zeros`",
+                               |db| {
+                let sugg = Sugg::hir(cx, left1, "...").maybe_par();
+                db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() > {}", sugg, n.count_ones()));
+            });
+        }}
     }
 }
 
index f1998235d3064bbf464a31506fa61060409f6b07..0c1c14f5b8c89dc6bc9403e818761d7f4a6ae266 100644 (file)
@@ -380,6 +380,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
         attrs::USELESS_ATTRIBUTE,
         bit_mask::BAD_BIT_MASK,
         bit_mask::INEFFECTIVE_BIT_MASK,
+        bit_mask::VERBOSE_BIT_MASK,
         blacklisted_name::BLACKLISTED_NAME,
         block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR,
         block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
index 38a68b2831b03ae26549e911e87a6a08eb1bc999..64f5e0f2045620a554dd4866eecb2d35560b7457 100644 (file)
@@ -6,6 +6,20 @@ error: &-masking with zero
    |
    = note: `-D bad-bit-mask` implied by `-D warnings`
 
+error: bit mask could be simplified with a call to `trailing_zeros`
+  --> bit_masks.rs:12:5
+   |
+12 |     x & 0 == 0;
+   |     ^^^^^^^^^^ help: try `x.trailing_zeros() > 0`
+   |
+   = note: `-D verbose-bit-mask` implied by `-D warnings`
+
+error: bit mask could be simplified with a call to `trailing_zeros`
+  --> bit_masks.rs:14:5
+   |
+14 |     x & 1 == 0; //ok, compared with zero
+   |     ^^^^^^^^^^ help: try `x.trailing_zeros() > 1`
+
 error: incompatible bit mask: `_ & 2` can never be equal to `1`
   --> bit_masks.rs:15:5
    |
@@ -92,7 +106,7 @@ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared
 55 |     x | 1 >= 8;
    |     ^^^^^^^^^^
 
-error: aborting due to 15 previous errors
+error: aborting due to 17 previous errors
 
 
 To learn more, run the command again with --verbose.
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4fb608c7bf15906df5c8530c4c024c70434cd5e2 100644 (file)
@@ -0,0 +1,18 @@
+error: bit mask could be simplified with a call to `trailing_zeros`
+ --> trailing_zeros.rs:7:31
+  |
+7 |     let _ = #[clippy(author)] (x & 0b1111 == 0);  // suggest trailing_zeros
+  |                               ^^^^^^^^^^^^^^^^^ help: try `x.trailing_zeros() > 4`
+  |
+  = note: `-D verbose-bit-mask` implied by `-D warnings`
+
+error: bit mask could be simplified with a call to `trailing_zeros`
+ --> trailing_zeros.rs:8:13
+  |
+8 |     let _ = x & 0b11111 == 0; // suggest trailing_zeros
+  |             ^^^^^^^^^^^^^^^^ help: try `x.trailing_zeros() > 5`
+
+error: aborting due to 2 previous errors
+
+
+To learn more, run the command again with --verbose.
index 7f1e8a60096a4d93dcf50e2b7c5aee226c3a7e27..98025316da4d22cf69be068693486b5382d8fa6f 100644 (file)
@@ -9,6 +9,6 @@ if_let_chain!{[
     let LitKind::Int(15, _) = lit.node,
     let Expr_::ExprLit(ref lit1) = right.node,
     let LitKind::Int(0, _) = lit1.node,
-]} {
+], {
     // report your lint here
-}
+}}