{flat_,}map_identity: recognize |[x, y]| [x, y] as an identity function as well (#15229)

changelog: [`map_identity`,`flat_map_identity`]: also recognize `|[x,
y]| [x, y]`

fixes rust-lang/rust-clippy#15198
This commit is contained in:
Timo 2025-07-12 13:10:23 +00:00 committed by GitHub
commit 3c3ee9bddb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 75 additions and 5 deletions

View file

@ -1896,6 +1896,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// * `|x| { return x }`
/// * `|x| { return x; }`
/// * `|(x, y)| (x, y)`
/// * `|[x, y]| [x, y]`
///
/// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
@ -1906,9 +1907,9 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
.get(pat.hir_id)
.is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
{
// If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics,
// the inner patterns become references. Don't consider this the identity function
// as that changes types.
// If the parameter is `(x, y)` of type `&(T, T)`, or `[x, y]` of type `&[T; 2]`, then
// due to match ergonomics, the inner patterns become references. Don't consider this
// the identity function as that changes types.
return false;
}
@ -1921,6 +1922,13 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
{
pats.iter().zip(tup).all(|(pat, expr)| check_pat(cx, pat, expr))
},
(PatKind::Slice(before, slice, after), ExprKind::Array(arr))
if slice.is_none() && before.len() + after.len() == arr.len() =>
{
(before.iter().chain(after))
.zip(arr)
.all(|(pat, expr)| check_pat(cx, pat, expr))
},
_ => false,
}
}

View file

@ -16,3 +16,16 @@ fn main() {
let _ = iterator.flatten();
//~^ flat_map_identity
}
fn issue15198() {
let x = [[1, 2], [3, 4]];
// don't lint: this is an `Iterator<Item = &[i32, i32]>`
// match ergonomics makes the binding patterns into references
// so that its type changes to `Iterator<Item = [&i32, &i32]>`
let _ = x.iter().flat_map(|[x, y]| [x, y]);
let _ = x.iter().flat_map(|x| [x[0]]);
// no match ergonomics for `[i32, i32]`
let _ = x.iter().copied().flatten();
//~^ flat_map_identity
}

View file

@ -16,3 +16,16 @@ fn main() {
let _ = iterator.flat_map(|x| return x);
//~^ flat_map_identity
}
fn issue15198() {
let x = [[1, 2], [3, 4]];
// don't lint: this is an `Iterator<Item = &[i32, i32]>`
// match ergonomics makes the binding patterns into references
// so that its type changes to `Iterator<Item = [&i32, &i32]>`
let _ = x.iter().flat_map(|[x, y]| [x, y]);
let _ = x.iter().flat_map(|x| [x[0]]);
// no match ergonomics for `[i32, i32]`
let _ = x.iter().copied().flat_map(|[x, y]| [x, y]);
//~^ flat_map_identity
}

View file

@ -19,5 +19,11 @@ error: use of `flat_map` with an identity function
LL | let _ = iterator.flat_map(|x| return x);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
error: aborting due to 3 previous errors
error: use of `flat_map` with an identity function
--> tests/ui/flat_map_identity.rs:29:31
|
LL | let _ = x.iter().copied().flat_map(|[x, y]| [x, y]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
error: aborting due to 4 previous errors

View file

@ -87,3 +87,15 @@ fn issue13904() {
let _ = { it }.next();
//~^ map_identity
}
// same as `issue11764`, but for arrays
fn issue15198() {
let x = [[1, 2], [3, 4]];
// don't lint: `&[i32; 2]` becomes `[&i32; 2]`
let _ = x.iter().map(|[x, y]| [x, y]);
let _ = x.iter().map(|x| [x[0]]).map(|[x]| x);
// no match ergonomics for `[i32, i32]`
let _ = x.iter().copied();
//~^ map_identity
}

View file

@ -93,3 +93,15 @@ fn issue13904() {
let _ = { it }.map(|x| x).next();
//~^ map_identity
}
// same as `issue11764`, but for arrays
fn issue15198() {
let x = [[1, 2], [3, 4]];
// don't lint: `&[i32; 2]` becomes `[&i32; 2]`
let _ = x.iter().map(|[x, y]| [x, y]);
let _ = x.iter().map(|x| [x[0]]).map(|[x]| x);
// no match ergonomics for `[i32, i32]`
let _ = x.iter().copied().map(|[x, y]| [x, y]);
//~^ map_identity
}

View file

@ -87,5 +87,11 @@ error: unnecessary map of the identity function
LL | let _ = { it }.map(|x| x).next();
| ^^^^^^^^^^^ help: remove the call to `map`
error: aborting due to 13 previous errors
error: unnecessary map of the identity function
--> tests/ui/map_identity.rs:105:30
|
LL | let _ = x.iter().copied().map(|[x, y]| [x, y]);
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
error: aborting due to 14 previous errors