Skip to content

Commit 40edb89

Browse files
author
Yusuf Raji
committed
Lint closures that only bind other args with no other expressions
1 parent d2dbd86 commit 40edb89

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

clippy_lints/src/single_option_map.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,25 @@ impl<'tcx> LateLintPass<'tcx> for SingleOptionMap {
5858
&& is_type_diagnostic_item(cx, callee_type, sym::Option)
5959
&& let ExprKind::Path(_path) = callee.kind
6060
&& let Res::Local(_id) = path_res(cx, callee)
61+
&& matches!(path_res(cx, callee), Res::Local(_id))
6162
&& !matches!(args[0].kind, ExprKind::Path(_))
6263
{
64+
if let ExprKind::Closure(closure) = args[0].kind {
65+
let Body { params: [..], value } = cx.tcx.hir().body(closure.body);
66+
if let ExprKind::Call(func, f_args) = value.kind
67+
&& matches!(func.kind, ExprKind::Path(_))
68+
&& f_args.iter().all(|arg| matches!(arg.kind, ExprKind::Path(_)))
69+
{
70+
return;
71+
} else if let ExprKind::MethodCall(_segment, receiver, method_args, _span) = value.kind
72+
&& matches!(receiver.kind, ExprKind::Path(_))
73+
&& method_args.iter().all(|arg| matches!(arg.kind, ExprKind::Path(_)))
74+
&& method_args.iter().all(|arg| matches!(path_res(cx, arg), Res::Local(_)))
75+
{
76+
return;
77+
}
78+
}
79+
6380
span_lint_and_help(
6481
cx,
6582
SINGLE_OPTION_MAP,

tests/ui/single_option_map.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ fn manipulate_opt_explicit(opt_i: Option<i32>) -> Option<i32> {
4040
opt_i.map(|x| manipulate(x))
4141
}
4242

43+
// No lint
44+
fn multi_args(a: String, b: bool, c: u64) -> String {
45+
a
46+
}
47+
48+
// No lint: contains only map of a closure that binds other arguments
49+
fn multi_args_opt(a: Option<String>, b: bool, c: u64) -> Option<String> {
50+
a.map(|a| multi_args(a, b, c))
51+
}
52+
4353
fn main() {
4454
let answer = Some(42u32);
4555
let h_result = h(answer);

tests/ui/single_option_map.stderr

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,5 @@ LL | | }
2222
|
2323
= help: move the `.map` to the caller or to an `_opt` function
2424

25-
error: `fn` that only maps over argument
26-
--> tests/ui/single_option_map.rs:39:1
27-
|
28-
LL | / fn manipulate_opt_explicit(opt_i: Option<i32>) -> Option<i32> {
29-
LL | | opt_i.map(|x| manipulate(x))
30-
LL | | }
31-
| |_^
32-
|
33-
= help: move the `.map` to the caller or to an `_opt` function
34-
35-
error: aborting due to 3 previous errors
25+
error: aborting due to 2 previous errors
3626

0 commit comments

Comments
 (0)