[iter_overeager_cloned]: detect .cloned().all() and .cloned().any()

This commit is contained in:
lengyijun 2023-08-20 09:14:52 +08:00
parent 4932d05733
commit fb6fad20c8
5 changed files with 36 additions and 14 deletions

View File

@ -21,7 +21,7 @@ pub(super) enum Op<'a> {
RmCloned,
// rm `.cloned()`
// e.g. `map` `for_each`
// e.g. `map` `for_each` `all` `any`
NeedlessMove(&'a str, &'a Expr<'a>),
// later `.cloned()`

View File

@ -3873,6 +3873,12 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
zst_offset::check(cx, expr, recv);
},
("all", [arg]) => {
if let Some(("cloned", recv2, [], _, _)) = method_call(recv) {
iter_overeager_cloned::check(cx, expr, recv, recv2,
iter_overeager_cloned::Op::NeedlessMove(name, arg), false);
}
}
("and_then", [arg]) => {
let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg);
@ -3880,12 +3886,16 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
}
},
("any", [arg]) if let ExprKind::Closure(arg) = arg.kind
&& let body = cx.tcx.hir().body(arg.body)
&& let [param] = body.params
&& let Some(("chars", recv, _, _, _)) = method_call(recv) =>
{
string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
("any", [arg]) => {
match method_call(recv) {
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::NeedlessMove(name, arg), false),
Some(("chars", recv, _, _, _)) if let ExprKind::Closure(arg) = arg.kind
&& let body = cx.tcx.hir().body(arg.body)
&& let [param] = body.params => {
string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
}
_ => {}
}
}
("arg", [arg]) => {
suspicious_command_arg_space::check(cx, recv, arg, span);

View File

@ -63,11 +63,9 @@ fn main() {
let _ = vec.iter().for_each(|x| assert!(!x.is_empty()));
// Not implemented yet
let _ = vec.iter().cloned().all(|x| x.len() == 1);
let _ = vec.iter().all(|x| x.len() == 1);
// Not implemented yet
let _ = vec.iter().cloned().any(|x| x.len() == 1);
let _ = vec.iter().any(|x| x.len() == 1);
// Should probably stay as it is.
let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);

View File

@ -64,10 +64,8 @@ fn bar<'a>(iter: impl Iterator<Item = &'a S<'a>> + 'a, target: String) -> impl I
let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty()));
// Not implemented yet
let _ = vec.iter().cloned().all(|x| x.len() == 1);
// Not implemented yet
let _ = vec.iter().cloned().any(|x| x.len() == 1);
// Should probably stay as it is.

View File

@ -146,5 +146,21 @@ LL | let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty()));
| |
| help: try: `.for_each(|x| assert!(!x.is_empty()))`
error: aborting due to 17 previous errors
error: unneeded cloning of iterator items
--> $DIR/iter_overeager_cloned.rs:67:13
|
LL | let _ = vec.iter().cloned().all(|x| x.len() == 1);
| ^^^^^^^^^^-------------------------------
| |
| help: try: `.all(|x| x.len() == 1)`
error: unneeded cloning of iterator items
--> $DIR/iter_overeager_cloned.rs:69:13
|
LL | let _ = vec.iter().cloned().any(|x| x.len() == 1);
| ^^^^^^^^^^-------------------------------
| |
| help: try: `.any(|x| x.len() == 1)`
error: aborting due to 19 previous errors