Merge pull request #202 from birkenfeld/unit_cmp

new lint: comparing unit types (fixes #201)
This commit is contained in:
llogiq 2015-08-19 08:34:19 +02:00
commit bbc917fef0
4 changed files with 49 additions and 0 deletions

View File

@ -45,6 +45,7 @@ string_add | allow | using `x + ..` where x is a `String`; suggests
string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead
string_to_string | warn | calling `String.to_string()` which is a no-op
toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`)
unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively)
zero_width_space | deny | using a zero-width space in a string literal, which is confusing
To use, add the following lines to your Cargo.toml:

View File

@ -64,6 +64,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box returns::ReturnPass as LintPassObject);
reg.register_lint_pass(box methods::MethodsPass as LintPassObject);
reg.register_lint_pass(box types::LetPass as LintPassObject);
reg.register_lint_pass(box types::UnitCmp as LintPassObject);
reg.register_lint_pass(box loops::LoopsPass as LintPassObject);
reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject);
reg.register_lint_pass(box ranges::StepByZero as LintPassObject);
@ -105,6 +106,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
types::BOX_VEC,
types::LET_UNIT_VALUE,
types::LINKEDLIST,
types::UNIT_CMP,
unicode::NON_ASCII_LITERAL,
unicode::ZERO_WIDTH_SPACE,
]);

View File

@ -1,6 +1,7 @@
use rustc::lint::*;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::ptr::P;
use rustc::middle::ty;
use syntax::codemap::ExpnInfo;
@ -107,3 +108,31 @@ impl LintPass for LetPass {
|info| check_let_unit(cx, decl, info));
}
}
declare_lint!(pub UNIT_CMP, Warn,
"comparing unit values (which is always `true` or `false`, respectively)");
#[allow(missing_copy_implementations)]
pub struct UnitCmp;
impl LintPass for UnitCmp {
fn get_lints(&self) -> LintArray {
lint_array!(UNIT_CMP)
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
if let ExprBinary(ref cmp, ref left, _) = expr.node {
let op = cmp.node;
let sty = &cx.tcx.expr_ty(left).sty;
if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) {
let result = match op {
BiEq | BiLe | BiGe => "true",
_ => "false"
};
span_lint(cx, UNIT_CMP, expr.span, &format!(
"{}-comparison of unit values detected. This will always be {}",
binop_to_string(op), result));
}
}
}
}

17
tests/compile-fail/unit_cmp.rs Executable file
View File

@ -0,0 +1,17 @@
#![feature(plugin)]
#![plugin(clippy)]
#![deny(unit_cmp)]
fn main() {
// this is fine
if true == false {
}
// this warns
if { true; } == { false; } { //~ERROR ==-comparison of unit values detected. This will always be true
}
if { true; } > { false; } { //~ERROR >-comparison of unit values detected. This will always be false
}
}