Skip to content

Commit 0b60531

Browse files
committed
[map_identity]: allow closure with type annotations
1 parent 33f49f3 commit 0b60531

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

clippy_utils/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,6 +2029,10 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
20292029

20302030
/// Checks if an expression represents the identity function
20312031
/// Only examines closures and `std::convert::identity`
2032+
///
2033+
/// Closure bindings with type annotations and `std::convert::identity` with generic args
2034+
/// are not considered identity functions because they can guide type inference,
2035+
/// and removing it may lead to compile errors.
20322036
pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
20332037
/// Checks if a function's body represents the identity function. Looks for bodies of the form:
20342038
/// * `|x| x`
@@ -2070,8 +2074,18 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
20702074
}
20712075

20722076
match expr.kind {
2073-
ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
2074-
_ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
2077+
ExprKind::Closure(&Closure { body, fn_decl, .. })
2078+
if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) =>
2079+
{
2080+
is_body_identity_function(cx, cx.tcx.hir().body(body))
2081+
},
2082+
ExprKind::Path(QPath::Resolved(_, path))
2083+
if path.segments.iter().all(|seg| seg.infer_args)
2084+
&& let Some(did) = path.res.opt_def_id() =>
2085+
{
2086+
match_def_path(cx, did, &paths::CONVERT_IDENTITY)
2087+
},
2088+
_ => false,
20752089
}
20762090
}
20772091

tests/ui/map_identity.fixed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ fn main() {
1717
});
1818
let _: Result<u32, u32> = Ok(1);
1919
let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
20+
// : u32 guides type inference
21+
let _ = Ok(1).map_err(|a: u32| a);
22+
let _ = Ok(1).map_err(std::convert::identity::<u32>);
2023
}
2124

2225
fn not_identity(x: &u16) -> u16 {

tests/ui/map_identity.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ fn main() {
1919
});
2020
let _: Result<u32, u32> = Ok(1).map_err(|a| a);
2121
let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
22+
// : u32 guides type inference
23+
let _ = Ok(1).map_err(|a: u32| a);
24+
let _ = Ok(1).map_err(std::convert::identity::<u32>);
2225
}
2326

2427
fn not_identity(x: &u16) -> u16 {

0 commit comments

Comments
 (0)