Skip to content

Commit 8596bc0

Browse files
committed
[WIP] Working on some changes
When checking if a function is an identity function, try to use existing functionalities. Some cases are no longer covered, but I believe that's ok and there were some bugs.
1 parent 00e5e1b commit 8596bc0

File tree

5 files changed

+41
-65
lines changed

5 files changed

+41
-65
lines changed
Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::peel_blocks;
2+
use clippy_utils::is_expr_identity_function;
33
use clippy_utils::res::MaybeDef;
44
use clippy_utils::source::snippet;
55
use rustc_errors::Applicability;
6-
use rustc_hir as hir;
7-
use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath};
6+
use rustc_hir::Expr;
7+
88
use rustc_lint::LateContext;
99
use rustc_span::symbol::sym;
1010

1111
use super::UNNECESSARY_RESULT_MAP_OR_ELSE;
12-
use super::utils::get_last_chain_binding_hir_id;
1312

1413
fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
1514
let msg = "unused \"map closure\" when calling `Result::map_or_else` value";
@@ -26,22 +25,6 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &E
2625
);
2726
}
2827

29-
fn handle_qpath(
30-
cx: &LateContext<'_>,
31-
expr: &Expr<'_>,
32-
recv: &Expr<'_>,
33-
def_arg: &Expr<'_>,
34-
expected_hir_id: HirId,
35-
qpath: QPath<'_>,
36-
) {
37-
if let QPath::Resolved(_, path) = qpath
38-
&& let hir::def::Res::Local(hir_id) = path.res
39-
&& expected_hir_id == hir_id
40-
{
41-
emit_lint(cx, expr, recv, def_arg);
42-
}
43-
}
44-
4528
/// lint use of `_.map_or_else(|err| err, |n| n)` for `Result`s.
4629
pub(super) fn check<'tcx>(
4730
cx: &LateContext<'tcx>,
@@ -51,30 +34,7 @@ pub(super) fn check<'tcx>(
5134
map_arg: &'tcx Expr<'_>,
5235
) {
5336
// lint if the caller of `map_or_else()` is a `Result`
54-
if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result)
55-
&& let ExprKind::Closure(&Closure { body, .. }) = map_arg.kind
56-
&& let body = cx.tcx.hir_body(body)
57-
&& let Some(first_param) = body.params.first()
58-
{
59-
let body_expr = peel_blocks(body.value);
60-
61-
match body_expr.kind {
62-
ExprKind::Path(qpath) => {
63-
handle_qpath(cx, expr, recv, def_arg, first_param.pat.hir_id, qpath);
64-
},
65-
// If this is a block (that wasn't peeled off), then it means there are statements.
66-
ExprKind::Block(block, _) => {
67-
if let Some(block_expr) = block.expr
68-
// First we ensure that this is a "binding chain" (each statement is a binding
69-
// of the previous one) and that it is a binding of the closure argument.
70-
&& let Some(last_chain_binding_id) =
71-
get_last_chain_binding_hir_id(first_param.pat.hir_id, block.stmts)
72-
&& let ExprKind::Path(qpath) = block_expr.kind
73-
{
74-
handle_qpath(cx, expr, recv, def_arg, last_chain_binding_id, qpath);
75-
}
76-
},
77-
_ => {},
78-
}
37+
if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result) && is_expr_identity_function(cx, map_arg) {
38+
emit_lint(cx, expr, recv, def_arg);
7939
}
8040
}

clippy_utils/src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1785,6 +1785,8 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
17851785
return false;
17861786
};
17871787

1788+
let mut param_pat = param.pat;
1789+
17881790
let mut expr = func.value;
17891791
loop {
17901792
match expr.kind {
@@ -1813,7 +1815,25 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
18131815
return false;
18141816
}
18151817
},
1816-
_ => return is_expr_identity_of_pat(cx, param.pat, expr, true),
1818+
ExprKind::Block(
1819+
&Block {
1820+
stmts, expr: Some(e), ..
1821+
},
1822+
_,
1823+
) => {
1824+
for stmt in stmts {
1825+
if let StmtKind::Let(local) = stmt.kind
1826+
&& let Some(init) = local.init
1827+
&& is_expr_identity_of_pat(cx, param_pat, init, true)
1828+
{
1829+
param_pat = local.pat;
1830+
} else {
1831+
return false;
1832+
}
1833+
}
1834+
expr = e;
1835+
},
1836+
_ => return is_expr_identity_of_pat(cx, param_pat, expr, true),
18171837
}
18181838
}
18191839
}

tests/ui/unnecessary_result_map_or_else.fixed

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ fn main() {
1111
x.unwrap_or_else(|err: ()| err);
1212
//~^ unnecessary_result_map_or_else
1313

14-
// Auto-deref.
15-
let y = String::new();
16-
let x: Result<&String, &String> = Ok(&y);
17-
let y: &str = x.unwrap_or_else(|err| err);
18-
//~^ unnecessary_result_map_or_else
19-
2014
// Temporary variable.
2115
let x: Result<(), ()> = Ok(());
2216
x.unwrap_or_else(|err| err);
@@ -61,4 +55,8 @@ fn main() {
6155
y
6256
},
6357
);
58+
59+
let x: Result<((), ()), ((), ())> = Ok(((), ()));
60+
x.unwrap_or_else(|err| err);
61+
//~^ unnecessary_result_map_or_else
6462
}

tests/ui/unnecessary_result_map_or_else.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ fn main() {
1111
x.map_or_else(|err: ()| err, |n: ()| n);
1212
//~^ unnecessary_result_map_or_else
1313

14-
// Auto-deref.
15-
let y = String::new();
16-
let x: Result<&String, &String> = Ok(&y);
17-
let y: &str = x.map_or_else(|err| err, |n| n);
18-
//~^ unnecessary_result_map_or_else
19-
2014
// Temporary variable.
2115
let x: Result<(), ()> = Ok(());
2216
x.map_or_else(
@@ -69,4 +63,8 @@ fn main() {
6963
y
7064
},
7165
);
66+
67+
let x: Result<((), ()), ((), ())> = Ok(((), ()));
68+
x.map_or_else(|err| err, |(a, b)| (a, b));
69+
//~^ unnecessary_result_map_or_else
7270
}

tests/ui/unnecessary_result_map_or_else.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,7 @@ LL | x.map_or_else(|err: ()| err, |n: ()| n);
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err: ()| err)`
1515

1616
error: unused "map closure" when calling `Result::map_or_else` value
17-
--> tests/ui/unnecessary_result_map_or_else.rs:17:19
18-
|
19-
LL | let y: &str = x.map_or_else(|err| err, |n| n);
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
21-
22-
error: unused "map closure" when calling `Result::map_or_else` value
23-
--> tests/ui/unnecessary_result_map_or_else.rs:22:5
17+
--> tests/ui/unnecessary_result_map_or_else.rs:16:5
2418
|
2519
LL | / x.map_or_else(
2620
LL | |
@@ -31,5 +25,11 @@ LL | | },
3125
LL | | );
3226
| |_____^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
3327

28+
error: unused "map closure" when calling `Result::map_or_else` value
29+
--> tests/ui/unnecessary_result_map_or_else.rs:68:5
30+
|
31+
LL | x.map_or_else(|err| err, |(a, b)| (a, b));
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
33+
3434
error: aborting due to 4 previous errors
3535

0 commit comments

Comments
 (0)