diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c11be44c085..bd2da3f361b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -471,6 +471,7 @@ All notable changes to this project will be documented in this file. [`mutex_integer`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_integer [`needless_bool`]: https://github.com/Manishearth/rust-clippy/wiki#needless_bool [`needless_borrow`]: https://github.com/Manishearth/rust-clippy/wiki#needless_borrow +[`needless_borrowed_reference`]: https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference [`needless_continue`]: https://github.com/Manishearth/rust-clippy/wiki#needless_continue [`needless_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes [`needless_pass_by_value`]: https://github.com/Manishearth/rust-clippy/wiki#needless_pass_by_value diff --git a/README.md b/README.md index 4b79c11aa387..6f4770ae669f 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 199 lints included in this crate: +There are 200 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -290,6 +290,7 @@ name [mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a mutex for an integer type [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` [needless_borrow](https://github.com/Manishearth/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced +[needless_borrowed_reference](https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference) | warn | taking a needless borrowed reference [needless_continue](https://github.com/Manishearth/rust-clippy/wiki#needless_continue) | warn | `continue` statements that can be replaced by a rearrangement of code [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_pass_by_value](https://github.com/Manishearth/rust-clippy/wiki#needless_pass_by_value) | warn | functions taking arguments by value, but not consuming them in its body diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ec73e9d50d9a..1ef7f3d3513f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -115,6 +115,7 @@ pub mod mut_reference; pub mod mutex_atomic; pub mod needless_bool; pub mod needless_borrow; +pub mod needless_borrowed_ref; pub mod needless_continue; pub mod needless_pass_by_value; pub mod needless_update; @@ -475,6 +476,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_borrow::NEEDLESS_BORROW, + needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_continue::NEEDLESS_CONTINUE, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, needless_update::NEEDLESS_UPDATE, diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs new file mode 100644 index 000000000000..dd6f1f22bd6b --- /dev/null +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -0,0 +1,58 @@ +//! Checks for useless borrowed references. +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc::hir::{MutImmutable, Pat, PatKind, BindingMode}; +use rustc::ty; +use utils::{span_lint, in_macro}; + +/// **What it does:** Checks for useless borrowed references. +/// +/// **Why is this bad?** It is completely useless and make the code look more complex than it actually is. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let mut v = Vec::::new(); +/// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +/// ``` +/// This clojure takes a reference on something that has been matched as a reference and de-referenced. +/// As such, it could just be |a| a.is_empty() +declare_lint! { + pub NEEDLESS_BORROWED_REFERENCE, + Warn, + "taking a needless borrowed reference" +} + +#[derive(Copy, Clone)] +pub struct NeedlessBorrowedRef; + +impl LintPass for NeedlessBorrowedRef { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_BORROWED_REFERENCE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { + fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { + if in_macro(pat.span) { + // OK, simple enough, lints doesn't check in macro. + return; + } + + if_let_chain! {[ + // Pat is a pattern whose node + // is a binding which "involves" a immutable reference... + let PatKind::Binding(BindingMode::BindByRef(MutImmutable), ..) = pat.node, + // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). + let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, + // This is an immutable reference. + tam.mutbl == MutImmutable, + ], { + span_lint(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced") + }} + } +} +