new lint: warn if let-binding has unit value (fixes #74)

This commit is contained in:
Georg Brandl 2015-08-12 11:31:09 +02:00
parent 8bcd01ff47
commit e8fed074cf
3 changed files with 49 additions and 2 deletions

View file

@ -59,6 +59,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box strings::StringAdd as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject);
reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject);
reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject);
reg.register_lint_pass(box types::LetPass as LintPassObject);
reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::SINGLE_MATCH, misc::STR_TO_STRING,
@ -83,5 +84,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
misc::MODULO_ONE, misc::MODULO_ONE,
methods::OPTION_UNWRAP_USED, methods::OPTION_UNWRAP_USED,
methods::RESULT_UNWRAP_USED, methods::RESULT_UNWRAP_USED,
types::LET_UNIT_VALUE,
]); ]);
} }

View file

@ -1,10 +1,11 @@
use syntax::ptr::P; use syntax::ptr::P;
use syntax::ast; use syntax::ast;
use syntax::ast::*; use syntax::ast::*;
use rustc::middle::ty;
use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level};
use syntax::codemap::Span; use syntax::codemap::{ExpnInfo, Span};
use utils::{span_lint, span_help_and_lint}; use utils::{in_macro, snippet, span_lint, span_help_and_lint};
/// Handles all the linting of funky types /// Handles all the linting of funky types
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
@ -75,3 +76,34 @@ impl LintPass for TypePass {
} }
} }
} }
#[allow(missing_copy_implementations)]
pub struct LetPass;
declare_lint!(pub LET_UNIT_VALUE, Warn,
"Warn on let-binding a value of unit type");
fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
if in_macro(cx, info) { return; }
if let DeclLocal(ref local) = decl.node {
let bindtype = &cx.tcx.pat_ty(&*local.pat).sty;
if *bindtype == ty::TyTuple(vec![]) {
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
"this let-binding has unit value. Consider omitting `let {} =`.",
snippet(cx, local.pat.span, "..")));
}
}
}
impl LintPass for LetPass {
fn get_lints(&self) -> LintArray {
lint_array!(LET_UNIT_VALUE)
}
fn check_decl(&mut self, cx: &Context, decl: &Decl) {
cx.sess().codemap().with_expn_info(
decl.span.expn_id,
|info| check_let_unit(cx, decl, info));
}
}

13
tests/compile-fail/let_unit.rs Executable file
View file

@ -0,0 +1,13 @@
#![feature(plugin)]
#![plugin(clippy)]
#![deny(let_unit_value)]
fn main() {
let _x = println!("x"); //~ERROR this let-binding has unit value
let _y = 1; // this is fine
let _z = ((), 1); // this as well
if true {
let _a = (); //~ERROR
}
}