@@ -60,6 +60,7 @@ mod manual_ok_or;
60
60
mod manual_saturating_arithmetic;
61
61
mod manual_str_repeat;
62
62
mod manual_try_fold;
63
+ mod map_all_any_identity;
63
64
mod map_clone;
64
65
mod map_collect_result_unit;
65
66
mod map_err_ignore;
@@ -4166,6 +4167,31 @@ declare_clippy_lint! {
4166
4167
"calling `.first().is_some()` or `.first().is_none()` instead of `.is_empty()`"
4167
4168
}
4168
4169
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
+
4169
4195
pub struct Methods {
4170
4196
avoid_breaking_exported_api : bool ,
4171
4197
msrv : Msrv ,
@@ -4327,6 +4353,7 @@ impl_lint_pass!(Methods => [
4327
4353
NEEDLESS_CHARACTER_ITERATION ,
4328
4354
MANUAL_INSPECT ,
4329
4355
UNNECESSARY_MIN_OR_MAX ,
4356
+ MAP_ALL_ANY_IDENTITY ,
4330
4357
] ) ;
4331
4358
4332
4359
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4534,15 +4561,23 @@ impl Methods {
4534
4561
( "all" , [ arg] ) => {
4535
4562
unused_enumerate_index:: check ( cx, expr, recv, arg) ;
4536
4563
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
+ _ => { } ,
4546
4581
}
4547
4582
} ,
4548
4583
( "and_then" , [ arg] ) => {
@@ -4571,6 +4606,11 @@ impl Methods {
4571
4606
{
4572
4607
string_lit_chars_any:: check ( cx, expr, recv, param, peel_blocks ( body. value ) , & self . msrv ) ;
4573
4608
} ,
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
+ } ,
4574
4614
_ => { } ,
4575
4615
}
4576
4616
} ,
0 commit comments