diff --git a/README.md b/README.md index e19ab474c5e3..af4c3e80437c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 81 lints included in this crate: +There are 82 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -81,6 +81,7 @@ name [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unneeded_binding](https://github.com/Manishearth/rust-clippy/wiki#unneeded_binding) | warn | Type fields are bound when not necessary [unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop diff --git a/src/lib.rs b/src/lib.rs index 9ead05b93b2f..abb3f0425df0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ pub mod temporary_assignment; pub mod transmute; pub mod cyclomatic_complexity; pub mod escape; +pub mod misc_early; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -118,6 +119,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box transmute::UselessTransmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); reg.register_late_lint_pass(box escape::EscapePass); + reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -181,6 +183,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + misc_early::UNNEEDED_BINDING, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, diff --git a/src/misc_early.rs b/src/misc_early.rs new file mode 100644 index 000000000000..5bec753d3ebd --- /dev/null +++ b/src/misc_early.rs @@ -0,0 +1,48 @@ +//use rustc_front::hir::*; + +use rustc::lint::*; + +use syntax::ast::*; + +use utils::span_lint; + +declare_lint!(pub UNNEEDED_BINDING, Warn, + "Type fields are bound when not necessary"); + +#[derive(Copy, Clone)] +pub struct MiscEarly; + +impl LintPass for MiscEarly { + fn get_lints(&self) -> LintArray { + lint_array!(UNNEEDED_BINDING) + } +} + +impl EarlyLintPass for MiscEarly { + fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { + if let PatStruct(_, ref pfields, _) = pat.node { + let mut wilds = 0; + + for field in pfields { + if field.node.pat.node == PatWild { + wilds += 1; + } + } + if !pfields.is_empty() && wilds == pfields.len() { + span_lint(cx, UNNEEDED_BINDING, pat.span, + "All the struct fields are matched to a wildcard pattern, \ + consider using `..`."); + return; + } + if wilds > 0 { + for field in pfields { + if field.node.pat.node == PatWild { + span_lint(cx, UNNEEDED_BINDING, field.span, + "You matched a field with a wildcard pattern. \ + Consider using `..` instead"); + } + } + } + } + } +} diff --git a/src/mut_mut.rs b/src/mut_mut.rs index c361ab248312..06f76479c590 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -41,7 +41,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map_or_else( || { - if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = + if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, "this expression mutably borrows a mutable reference. \ diff --git a/src/mut_reference.rs b/src/mut_reference.rs index e9601e8650f1..8e089378929a 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -58,8 +58,8 @@ fn check_arguments(cx: &LateContext, arguments: &[P], type_definition: &Ty let parameters = &fn_type.sig.skip_binder().inputs; for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | + TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { if let ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("The function/method \"{}\" \ diff --git a/src/open_options.rs b/src/open_options.rs index 732852e16865..dd375d58a601 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -58,7 +58,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned {node: LitBool(lit), span: _} = **span { + if let Spanned {node: LitBool(lit), ..} = **span { if lit {Argument::True} else {Argument::False} } else { return; // The function is called with a literal diff --git a/src/shadow.rs b/src/shadow.rs index 2c68667fc32d..60197fcf9df5 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -62,7 +62,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } if is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { - let Local{ ref pat, ref ty, ref init, id: _, span, attrs: _ } = **local; + let Local{ ref pat, ref ty, ref init, span, .. } = **local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } if let Some(ref o) = *init { check_expr(cx, o, bindings); diff --git a/src/utils.rs b/src/utils.rs index 365fc1bf99d5..a602902d45fd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -167,8 +167,8 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { Some(NodeItem(&Item{ ref name, .. })) | - Some(NodeTraitItem(&TraitItem{ id: _, ref name, .. })) | - Some(NodeImplItem(&ImplItem{ id: _, ref name, .. })) => { + Some(NodeTraitItem(&TraitItem{ ref name, .. })) | + Some(NodeImplItem(&ImplItem{ ref name, .. })) => { Some(*name) } _ => None,