diff options
| author | Timo <30553356+y21@users.noreply.github.com> | 2025-07-12 13:10:23 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-12 13:10:23 +0000 |
| commit | 3c3ee9bddbab942ed4eb6af585cfc6f2fd755753 (patch) | |
| tree | 14d60ef67a9dc2bbaa509d3775fd73f56784868c | |
| parent | 3d7188d06df87b230b8464871f701397330535fb (diff) | |
| parent | e610584a9a6ff66cbebfcf517ab04c3bd612d271 (diff) | |
| download | rust-3c3ee9bddbab942ed4eb6af585cfc6f2fd755753.tar.gz rust-3c3ee9bddbab942ed4eb6af585cfc6f2fd755753.zip | |
`{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
| -rw-r--r-- | clippy_utils/src/lib.rs | 14 | ||||
| -rw-r--r-- | tests/ui/flat_map_identity.fixed | 13 | ||||
| -rw-r--r-- | tests/ui/flat_map_identity.rs | 13 | ||||
| -rw-r--r-- | tests/ui/flat_map_identity.stderr | 8 | ||||
| -rw-r--r-- | tests/ui/map_identity.fixed | 12 | ||||
| -rw-r--r-- | tests/ui/map_identity.rs | 12 | ||||
| -rw-r--r-- | tests/ui/map_identity.stderr | 8 |
7 files changed, 75 insertions, 5 deletions
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 2e03743e621..8b9cd6a54dd 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -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, } } diff --git a/tests/ui/flat_map_identity.fixed b/tests/ui/flat_map_identity.fixed index f6206232612..06a3eee9d84 100644 --- a/tests/ui/flat_map_identity.fixed +++ b/tests/ui/flat_map_identity.fixed @@ -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 +} diff --git a/tests/ui/flat_map_identity.rs b/tests/ui/flat_map_identity.rs index c59e749474e..1cab7d559d8 100644 --- a/tests/ui/flat_map_identity.rs +++ b/tests/ui/flat_map_identity.rs @@ -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 +} diff --git a/tests/ui/flat_map_identity.stderr b/tests/ui/flat_map_identity.stderr index 75137f5d9e5..18c863bf96d 100644 --- a/tests/ui/flat_map_identity.stderr +++ b/tests/ui/flat_map_identity.stderr @@ -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 diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed index 83b2dac5fc5..b82d3e6d956 100644 --- a/tests/ui/map_identity.fixed +++ b/tests/ui/map_identity.fixed @@ -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 +} diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs index e839c551364..c295bf87270 100644 --- a/tests/ui/map_identity.rs +++ b/tests/ui/map_identity.rs @@ -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 +} diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr index 9836f3b4cc5..9b624a0dc75 100644 --- a/tests/ui/map_identity.stderr +++ b/tests/ui/map_identity.stderr @@ -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 |
