@@ -60,6 +60,7 @@ mod manual_ok_or;
6060mod manual_saturating_arithmetic;
6161mod manual_str_repeat;
6262mod manual_try_fold;
63+ mod map_all_any_identity;
6364mod map_clone;
6465mod map_collect_result_unit;
6566mod map_err_ignore;
@@ -4166,6 +4167,31 @@ declare_clippy_lint! {
41664167 "calling `.first().is_some()` or `.first().is_none()` instead of `.is_empty()`"
41674168}
41684169
4170+ declare_clippy_lint ! {
4171+ /// ### What it does
4172+ /// Checks for usage of `.map(…)`, followed by `.all(identity)` or `.any(identity)`.
4173+ ///
4174+ /// ### Why is this bad?
4175+ /// The `.all(…)` or `.any(…)` methods can be called directly in place of `.map(…)`.
4176+ ///
4177+ /// ### Example
4178+ /// ```
4179+ /// # let mut v = [""].into_iter();
4180+ /// let e1 = v.iter().map(|s| s.is_empty()).all(|a| a);
4181+ /// let e2 = v.iter().map(|s| s.is_empty()).any(std::convert::identity);
4182+ /// ```
4183+ /// Use instead:
4184+ /// ```
4185+ /// # let mut v = [""].into_iter();
4186+ /// let e1 = v.iter().all(|s| s.is_empty());
4187+ /// let e2 = v.iter().any(|s| s.is_empty());
4188+ /// ```
4189+ #[ clippy:: version = "1.83.0" ]
4190+ pub MAP_ALL_ANY_IDENTITY ,
4191+ complexity,
4192+ "combine `.map(_)` followed by `.all(identity)`/`.any(identity)` into a single call"
4193+ }
4194+
41694195pub struct Methods {
41704196 avoid_breaking_exported_api : bool ,
41714197 msrv : Msrv ,
@@ -4327,6 +4353,7 @@ impl_lint_pass!(Methods => [
43274353 NEEDLESS_CHARACTER_ITERATION ,
43284354 MANUAL_INSPECT ,
43294355 UNNECESSARY_MIN_OR_MAX ,
4356+ MAP_ALL_ANY_IDENTITY ,
43304357] ) ;
43314358
43324359/// Extracts a method call name, args, and `Span` of the method name.
@@ -4534,15 +4561,23 @@ impl Methods {
45344561 ( "all" , [ arg] ) => {
45354562 unused_enumerate_index:: check ( cx, expr, recv, arg) ;
45364563 needless_character_iteration:: check ( cx, expr, recv, arg, true ) ;
4537- if let Some ( ( "cloned" , recv2, [ ] , _, _) ) = method_call ( recv) {
4538- iter_overeager_cloned:: check (
4539- cx,
4540- expr,
4541- recv,
4542- recv2,
4543- iter_overeager_cloned:: Op :: NeedlessMove ( arg) ,
4544- false ,
4545- ) ;
4564+ match method_call ( recv) {
4565+ Some ( ( "cloned" , recv2, [ ] , _, _) ) => {
4566+ iter_overeager_cloned:: check (
4567+ cx,
4568+ expr,
4569+ recv,
4570+ recv2,
4571+ iter_overeager_cloned:: Op :: NeedlessMove ( arg) ,
4572+ false ,
4573+ ) ;
4574+ } ,
4575+ Some ( ( "map" , _, [ map_arg] , _, map_call_span) )
4576+ if is_trait_method ( cx, expr, sym:: Iterator ) && is_trait_method ( cx, recv, sym:: Iterator ) =>
4577+ {
4578+ map_all_any_identity:: check ( cx, map_call_span, map_arg, call_span, arg, "all" ) ;
4579+ } ,
4580+ _ => { } ,
45464581 }
45474582 } ,
45484583 ( "and_then" , [ arg] ) => {
@@ -4571,6 +4606,11 @@ impl Methods {
45714606 {
45724607 string_lit_chars_any:: check ( cx, expr, recv, param, peel_blocks ( body. value ) , & self . msrv ) ;
45734608 } ,
4609+ Some ( ( "map" , _, [ map_arg] , _, map_call_span) )
4610+ if is_trait_method ( cx, expr, sym:: Iterator ) && is_trait_method ( cx, recv, sym:: Iterator ) =>
4611+ {
4612+ map_all_any_identity:: check ( cx, map_call_span, map_arg, call_span, arg, "any" ) ;
4613+ } ,
45744614 _ => { } ,
45754615 }
45764616 } ,
0 commit comments