diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9013985eaf..7e5dfa112cfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1152,6 +1152,7 @@ Released 2018-09-13 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting +[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr diff --git a/README.md b/README.md index 8bcfd8a8430c..389fe316ade2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 309 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 310 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3054f11c1769..705ec2e9fd8e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -800,6 +800,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, methods::STRING_EXTEND_CHARS, + methods::SUSPICIOUS_MAP, methods::TEMPORARY_CSTRING_AS_PTR, methods::UNNECESSARY_FILTER_MAP, methods::UNNECESSARY_FOLD, @@ -1033,6 +1034,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::FILTER_NEXT, methods::FLAT_MAP_IDENTITY, methods::SEARCH_IS_SOME, + methods::SUSPICIOUS_MAP, methods::UNNECESSARY_FILTER_MAP, methods::USELESS_ASREF, misc::SHORT_CIRCUIT_STATEMENT, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 0020dbd233d9..c8e3ca14ab11 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -18,7 +18,6 @@ use syntax::ast; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; -use crate::utils::paths; use crate::utils::sugg; use crate::utils::usage::mutated_variables; use crate::utils::{ @@ -28,6 +27,7 @@ use crate::utils::{ snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; +use crate::utils::{paths, span_help_and_lint}; declare_clippy_lint! { /// **What it does:** Checks for `.unwrap()` calls on `Option`s. @@ -889,6 +889,24 @@ declare_clippy_lint! { "using `.into_iter()` on a reference" } +declare_clippy_lint! { + /// **What it does:** Checks for calls to `map` followed by a `count`. + /// + /// **Why is this bad?** It looks suspicious. Maybe `map` was confused with `filter`. + /// If the `map` call is intentional, this should be rewritten. + /// + /// **Known problems:** None + /// + /// **Example:** + /// + /// ```rust + /// let _ = (0..3).map(|x| x + 2).count(); + /// ``` + pub SUSPICIOUS_MAP, + complexity, + "suspicious usage of map" +} + declare_lint_pass!(Methods => [ OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, @@ -927,6 +945,7 @@ declare_lint_pass!(Methods => [ UNNECESSARY_FILTER_MAP, INTO_ITER_ON_ARRAY, INTO_ITER_ON_REF, + SUSPICIOUS_MAP, ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { @@ -972,6 +991,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { ["as_mut"] => lint_asref(cx, expr, "as_mut", arg_lists[0]), ["fold", ..] => lint_unnecessary_fold(cx, expr, arg_lists[0]), ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), + ["count", "map"] => lint_suspicious_map(cx, expr), _ => {}, } @@ -2519,6 +2539,16 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_ } } +fn lint_suspicious_map(cx: &LateContext<'_, '_>, expr: &hir::Expr) { + span_help_and_lint( + cx, + SUSPICIOUS_MAP, + expr.span, + "this call to `map()` won't have an effect on the call to `count()`", + "make sure you did not confuse `map` with `filter`", + ); +} + /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { if let ty::Adt(_, substs) = ty.sty { diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 0df8370936c8..ff7db0a3da77 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 309] = [ +pub const ALL_LINTS: [Lint; 310] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1736,6 +1736,13 @@ pub const ALL_LINTS: [Lint; 309] = [ deprecation: None, module: "formatting", }, + Lint { + name: "suspicious_map", + group: "complexity", + desc: "suspicious usage of map", + deprecation: None, + module: "methods", + }, Lint { name: "suspicious_op_assign_impl", group: "correctness", diff --git a/tests/ui/suspicious_map.rs b/tests/ui/suspicious_map.rs new file mode 100644 index 000000000000..d838d8fde210 --- /dev/null +++ b/tests/ui/suspicious_map.rs @@ -0,0 +1,5 @@ +#![warn(clippy::suspicious_map)] + +fn main() { + let _ = (0..3).map(|x| x + 2).count(); +} diff --git a/tests/ui/suspicious_map.stderr b/tests/ui/suspicious_map.stderr new file mode 100644 index 000000000000..e6588f4691a1 --- /dev/null +++ b/tests/ui/suspicious_map.stderr @@ -0,0 +1,11 @@ +error: this call to `map()` won't have an effect on the call to `count()` + --> $DIR/suspicious_map.rs:4:13 + | +LL | let _ = (0..3).map(|x| x + 2).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::suspicious-map` implied by `-D warnings` + = help: make sure you did not confuse `map` with `filter` + +error: aborting due to previous error +