Skip to content

Commit

Permalink
[map_identity]: allow closure with type annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Sep 17, 2023
1 parent f54275f commit b71502a
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
18 changes: 16 additions & 2 deletions clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,10 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {

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

match expr.kind {
ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
_ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
ExprKind::Closure(&Closure { body, fn_decl, .. })
if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) =>
{
is_body_identity_function(cx, cx.tcx.hir().body(body))
},
ExprKind::Path(QPath::Resolved(_, path))
if path.segments.iter().all(|seg| seg.infer_args)
&& let Some(did) = path.res.opt_def_id() =>
{
match_def_path(cx, did, &paths::CONVERT_IDENTITY)
},
_ => false,
}
}

Expand Down
3 changes: 3 additions & 0 deletions tests/ui/map_identity.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ fn main() {
});
let _: Result<u32, u32> = Ok(1);
let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
// : u32 guides type inference
let _ = Ok(1).map_err(|a: u32| a);
let _ = Ok(1).map_err(std::convert::identity::<u32>);
}

fn not_identity(x: &u16) -> u16 {
Expand Down
3 changes: 3 additions & 0 deletions tests/ui/map_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ fn main() {
});
let _: Result<u32, u32> = Ok(1).map_err(|a| a);
let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
// : u32 guides type inference
let _ = Ok(1).map_err(|a: u32| a);
let _ = Ok(1).map_err(std::convert::identity::<u32>);
}

fn not_identity(x: &u16) -> u16 {
Expand Down

0 comments on commit b71502a

Please sign in to comment.