diff --git a/src/lib.rs b/src/lib.rs index fef678f66..27302b51b 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 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_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -83,5 +84,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + types::LET_UNIT_VALUE, ]); } diff --git a/src/types.rs b/src/types.rs index b03829660..4980046e0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,10 +1,11 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; +use rustc::middle::ty; 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 #[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)); + } +} diff --git a/tests/compile-fail/let_unit.rs b/tests/compile-fail/let_unit.rs new file mode 100755 index 000000000..e8620f862 --- /dev/null +++ b/tests/compile-fail/let_unit.rs @@ -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 + } +}