Skip to content

Commit f37e7f3

Browse files
committed
Auto merge of rust-lang#12109 - GuillaumeGomez:map-clone-call, r=llogiq
Handle "calls" inside the closure as well in `map_clone` lint Follow-up of rust-lang/rust-clippy#12104. I just realized that I didn't handle the case where the `clone` method was made as a call and not a method call. r? `@llogiq` changelog: Handle "calls" inside the closure as well in `map_clone` lint
2 parents adc5bc9 + f66e940 commit f37e7f3

File tree

4 files changed

+45
-16
lines changed

4 files changed

+45
-16
lines changed

clippy_lints/src/methods/map_clone.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,26 +61,39 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
6161
}
6262
}
6363
},
64+
hir::ExprKind::Call(call, [_]) => {
65+
if let hir::ExprKind::Path(qpath) = call.kind {
66+
handle_path(cx, call, &qpath, e, recv);
67+
}
68+
},
6469
_ => {},
6570
}
6671
},
6772
_ => {},
6873
}
6974
},
70-
hir::ExprKind::Path(qpath) => {
71-
if let Some(path_def_id) = cx.qpath_res(&qpath, arg.hir_id).opt_def_id()
72-
&& match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
73-
{
74-
// FIXME: It would be better to infer the type to check if it's copyable or not
75-
// to suggest to use `.copied()` instead of `.cloned()` where applicable.
76-
lint_path(cx, e.span, recv.span);
77-
}
78-
},
75+
hir::ExprKind::Path(qpath) => handle_path(cx, arg, &qpath, e, recv),
7976
_ => {},
8077
}
8178
}
8279
}
8380

81+
fn handle_path(
82+
cx: &LateContext<'_>,
83+
arg: &hir::Expr<'_>,
84+
qpath: &hir::QPath<'_>,
85+
e: &hir::Expr<'_>,
86+
recv: &hir::Expr<'_>,
87+
) {
88+
if let Some(path_def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
89+
&& match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
90+
{
91+
// FIXME: It would be better to infer the type to check if it's copyable or not
92+
// to suggest to use `.copied()` instead of `.cloned()` where applicable.
93+
lint_path(cx, e.span, recv.span);
94+
}
95+
}
96+
8497
fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool {
8598
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = path.kind {
8699
path.segments.len() == 1 && path.segments[0].ident == name

tests/ui/map_clone.fixed

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
clippy::iter_cloned_collect,
55
clippy::many_single_char_names,
66
clippy::redundant_clone,
7+
clippy::redundant_closure,
78
clippy::useless_vec
89
)]
910

@@ -60,4 +61,8 @@ fn main() {
6061

6162
let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
6263
}
64+
65+
let x = Some(String::new());
66+
let y = x.as_ref().cloned();
67+
//~^ ERROR: you are explicitly cloning with `.map()`
6368
}

tests/ui/map_clone.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
clippy::iter_cloned_collect,
55
clippy::many_single_char_names,
66
clippy::redundant_clone,
7+
clippy::redundant_closure,
78
clippy::useless_vec
89
)]
910

@@ -60,4 +61,8 @@ fn main() {
6061

6162
let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
6263
}
64+
65+
let x = Some(String::new());
66+
let y = x.as_ref().map(|x| String::clone(x));
67+
//~^ ERROR: you are explicitly cloning with `.map()`
6368
}

tests/ui/map_clone.stderr

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: you are using an explicit closure for copying elements
2-
--> $DIR/map_clone.rs:11:22
2+
--> $DIR/map_clone.rs:12:22
33
|
44
LL | let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
@@ -8,34 +8,40 @@ LL | let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
88
= help: to override `-D warnings` add `#[allow(clippy::map_clone)]`
99

1010
error: you are using an explicit closure for cloning elements
11-
--> $DIR/map_clone.rs:12:26
11+
--> $DIR/map_clone.rs:13:26
1212
|
1313
LL | let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
1515

1616
error: you are using an explicit closure for copying elements
17-
--> $DIR/map_clone.rs:13:23
17+
--> $DIR/map_clone.rs:14:23
1818
|
1919
LL | let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
2121

2222
error: you are using an explicit closure for copying elements
23-
--> $DIR/map_clone.rs:15:26
23+
--> $DIR/map_clone.rs:16:26
2424
|
2525
LL | let _: Option<u64> = Some(&16).map(|b| *b);
2626
| ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
2727

2828
error: you are using an explicit closure for copying elements
29-
--> $DIR/map_clone.rs:16:25
29+
--> $DIR/map_clone.rs:17:25
3030
|
3131
LL | let _: Option<u8> = Some(&1).map(|x| x.clone());
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
3333

3434
error: you are needlessly cloning iterator elements
35-
--> $DIR/map_clone.rs:27:29
35+
--> $DIR/map_clone.rs:28:29
3636
|
3737
LL | let _ = std::env::args().map(|v| v.clone());
3838
| ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
3939

40-
error: aborting due to 6 previous errors
40+
error: you are explicitly cloning with `.map()`
41+
--> $DIR/map_clone.rs:66:13
42+
|
43+
LL | let y = x.as_ref().map(|x| String::clone(x));
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.as_ref().cloned()`
45+
46+
error: aborting due to 7 previous errors
4147

0 commit comments

Comments
 (0)