]> git.lizzy.rs Git - rust.git/commitdiff
Add a lint to suggest uint == 0 over uint <= 0
authorscurest <scurest@users.noreply.github.com>
Fri, 29 Jan 2016 06:39:13 +0000 (00:39 -0600)
committerscurest <scurest@users.noreply.github.com>
Sat, 30 Jan 2016 03:21:12 +0000 (21:21 -0600)
README.md
src/escape.rs
src/lib.rs
src/types.rs
tests/compile-fail/absurd_unsigned_comparisons.rs [new file with mode: 0644]

index ec1dd7f6dbb3a7f93cf665565d71912e79197b59..0c94fb3383e1915234ec8998fb2394829c0666c6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,10 +6,11 @@ A collection of lints to catch common mistakes and improve your Rust code.
 [Jump to usage instructions](#usage)
 
 ##Lints
-There are 104 lints included in this crate:
+There are 105 lints included in this crate:
 
 name                                                                                                           | default | meaning
 ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+[absurd_unsigned_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_unsigned_comparisons)     | warn    | testing whether an unsigned integer is non-positive
 [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant)                             | warn    | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant
 [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask)                                   | warn    | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have)
 [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr)       | warn    | braces can be eliminated in conditions that are expressions, e.g `if { true } ...`
index 32dbbb992267d878ce3110c42a0c4e7fb8c05b4b..c54c43953358be98ac76c5f49b9cb63495572cc4 100644 (file)
@@ -135,7 +135,7 @@ fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region,
                                                                         .get(&borrow_id) {
                     if LoanCause::AutoRef == loan_cause {
                         // x.foo()
-                        if adj.autoderefs <= 0 {
+                        if adj.autoderefs == 0 {
                             self.set.remove(&lid); // Used without autodereffing (i.e. x.clone())
                         }
                     } else {
index 82bd2d39a1294c469c33a87ce91d09d34b69ebbf..3519fb9ee88e51fbe09fc2067671c32d4c1ad562 100644 (file)
@@ -146,6 +146,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_late_lint_pass(box types::CharLitAsU8);
     reg.register_late_lint_pass(box print::PrintLint);
     reg.register_late_lint_pass(box vec::UselessVec);
+    reg.register_late_lint_pass(box types::AbsurdUnsignedComparisons);
 
 
     reg.register_lint_group("clippy_pedantic", vec![
@@ -247,6 +248,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
         strings::STRING_LIT_AS_BYTES,
         temporary_assignment::TEMPORARY_ASSIGNMENT,
         transmute::USELESS_TRANSMUTE,
+        types::ABSURD_UNSIGNED_COMPARISONS,
         types::BOX_VEC,
         types::CHAR_LIT_AS_U8,
         types::LET_UNIT_VALUE,
index d41896cd490a68f4f3aa0f2cb09f8ef77d6fe240..0ab373bfa35c38ba32ba145eca5bde23c9d13b43 100644 (file)
@@ -557,3 +557,55 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
         }
     }
 }
+
+/// **What it does:** This lint checks for expressions where an unsigned integer is tested to be non-positive and suggests testing for equality with zero instead.
+///
+/// **Why is this bad?** `x <= 0` may mislead the reader into thinking `x` can be negative. `x == 0` makes explicit that zero is the only possibility.
+///
+/// **Known problems:** None
+///
+/// **Example:** `vec.len() <= 0`
+declare_lint!(pub ABSURD_UNSIGNED_COMPARISONS, Warn,
+              "testing whether an unsigned integer is non-positive");
+
+pub struct AbsurdUnsignedComparisons;
+
+impl LintPass for AbsurdUnsignedComparisons {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(ABSURD_UNSIGNED_COMPARISONS)
+    }
+}
+
+fn is_zero_lit(expr: &Expr) -> bool {
+    use syntax::ast::Lit_;
+
+    if let ExprLit(ref l) = expr.node {
+        if let Lit_::LitInt(val, _) = l.node {
+            return val == 0;
+        }
+    }
+    false
+}
+
+impl LateLintPass for AbsurdUnsignedComparisons {
+    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
+        if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node {
+            let op = cmp.node;
+
+            let comparee = match op {
+                BiLe if is_zero_lit(rhs) => lhs, // x <= 0
+                BiGe if is_zero_lit(lhs) => rhs, // 0 >= x
+                _ => return,
+            };
+
+            if let ty::TyUint(_) = cx.tcx.expr_ty(comparee).sty {
+                if !in_macro(cx, expr.span) {
+                    let msg = "testing whether an unsigned integer is non-positive";
+                    let help = format!("consider using {} == 0 instead",
+                                       snippet(cx, comparee.span, "x"));
+                    span_help_and_lint(cx, ABSURD_UNSIGNED_COMPARISONS, expr.span, msg, &help);
+                }
+            }
+        }
+    }
+}
diff --git a/tests/compile-fail/absurd_unsigned_comparisons.rs b/tests/compile-fail/absurd_unsigned_comparisons.rs
new file mode 100644 (file)
index 0000000..d7817da
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(plugin)]
+#![plugin(clippy)]
+
+#![allow(unused)]
+
+#[deny(absurd_unsigned_comparisons)]
+fn main() {
+    1u32 <= 0; //~ERROR testing whether an unsigned integer is non-positive
+    1u8 <= 0; //~ERROR testing whether an unsigned integer is non-positive
+    1i32 <= 0;
+    0 >= 1u32; //~ERROR testing whether an unsigned integer is non-positive
+    0 >= 1;
+    1u32 > 0;
+}