[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 } ...`
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![
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,
}
}
}
+
+/// **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);
+ }
+ }
+ }
+ }
+}