diff options
| author | bors <bors@rust-lang.org> | 2023-11-11 14:58:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-11-11 14:58:00 +0000 |
| commit | d487579efd3c6b7766f820bbe4b6be0f6d420dad (patch) | |
| tree | 068c94f84adb74e8573606b64e1b62cbb39e8467 | |
| parent | 4a0c36d648b8442698e5c7b6bfc3bb42eeffdbd2 (diff) | |
| parent | b2cf8f7a24d33914a51fcb0048bfaba11868f471 (diff) | |
| download | rust-d487579efd3c6b7766f820bbe4b6be0f6d420dad.tar.gz rust-d487579efd3c6b7766f820bbe4b6be0f6d420dad.zip | |
Auto merge of #11792 - y21:issue11764, r=llogiq
[`map_identity`]: respect match ergonomics Fixes #11764 Note: the original tests before this were slightly wrong themselves already and had to be changed. They were calling `map` on an iterator of `&(i32, i32)`s, so this PR would stop linting there, but they were meant to test something else unrelated to binding modes, so I just changed them to remove the references so that it iterates over owned values and they all bind by value. This way they continue to test what they checked for before: the identity function for tuple patterns. changelog: [`map_identity`]: respect match ergonomics
| -rw-r--r-- | clippy_utils/src/lib.rs | 12 | ||||
| -rw-r--r-- | tests/ui/map_identity.fixed | 42 | ||||
| -rw-r--r-- | tests/ui/map_identity.rs | 42 | ||||
| -rw-r--r-- | tests/ui/map_identity.stderr | 32 |
4 files changed, 85 insertions, 43 deletions
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 21225dc7098..b921ea116fe 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2023,6 +2023,18 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead. fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool { + if cx + .typeck_results() + .pat_binding_modes() + .get(pat.hir_id) + .is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_))) + { + // 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. + return false; + } + match (pat.kind, expr.kind) { (PatKind::Binding(_, id, _, _), _) => { path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty() diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed index 62b0ba01860..53ebfb40ba0 100644 --- a/tests/ui/map_identity.fixed +++ b/tests/ui/map_identity.fixed @@ -24,28 +24,40 @@ fn main() { fn issue7189() { // should lint - let x = [(1, 2), (3, 4)]; - let _ = x.iter(); - let _ = x.iter(); - let _ = x.iter(); + let x = [(1, 2), (3, 4)].iter().copied(); + let _ = x.clone(); + let _ = x.clone(); + let _ = x.clone(); - let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))]; - let _ = y.iter(); + let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); + let _ = y.clone(); // should not lint - let _ = x.iter().map(|(x, y)| (x, y, y)); - let _ = x.iter().map(|(x, _y)| (x,)); - let _ = x.iter().map(|(x, _)| (x,)); - let _ = x.iter().map(|(x, ..)| (x,)); - let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z))); + let _ = x.clone().map(|(x, y)| (x, y, y)); + let _ = x.clone().map(|(x, _y)| (x,)); + let _ = x.clone().map(|(x, _)| (x,)); + let _ = x.clone().map(|(x, ..)| (x,)); + let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z))); + .clone() + .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); + .clone() + .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); } fn not_identity(x: &u16) -> u16 { *x } + +fn issue11764() { + 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().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(); +} diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs index b7f4c99f273..c646c056859 100644 --- a/tests/ui/map_identity.rs +++ b/tests/ui/map_identity.rs @@ -26,30 +26,42 @@ fn main() { fn issue7189() { // should lint - let x = [(1, 2), (3, 4)]; - let _ = x.iter().map(|(x, y)| (x, y)); - let _ = x.iter().map(|(x, y)| { + let x = [(1, 2), (3, 4)].iter().copied(); + let _ = x.clone().map(|(x, y)| (x, y)); + let _ = x.clone().map(|(x, y)| { return (x, y); }); - let _ = x.iter().map(|(x, y)| return (x, y)); + let _ = x.clone().map(|(x, y)| return (x, y)); - let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))]; - let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); + let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); + let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); // should not lint - let _ = x.iter().map(|(x, y)| (x, y, y)); - let _ = x.iter().map(|(x, _y)| (x,)); - let _ = x.iter().map(|(x, _)| (x,)); - let _ = x.iter().map(|(x, ..)| (x,)); - let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z))); + let _ = x.clone().map(|(x, y)| (x, y, y)); + let _ = x.clone().map(|(x, _y)| (x,)); + let _ = x.clone().map(|(x, _)| (x,)); + let _ = x.clone().map(|(x, ..)| (x,)); + let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z))); + .clone() + .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); + .clone() + .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); } fn not_identity(x: &u16) -> u16 { *x } + +fn issue11764() { + 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().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)); +} diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr index 4ca24b0b04c..ea077d66d64 100644 --- a/tests/ui/map_identity.stderr +++ b/tests/ui/map_identity.stderr @@ -41,31 +41,37 @@ LL | let _: Result<u32, u32> = Ok(1).map_err(|a| a); | ^^^^^^^^^^^^^^^ help: remove the call to `map_err` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:30:21 + --> $DIR/map_identity.rs:30:22 | -LL | let _ = x.iter().map(|(x, y)| (x, y)); - | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = x.clone().map(|(x, y)| (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:31:21 + --> $DIR/map_identity.rs:31:22 | -LL | let _ = x.iter().map(|(x, y)| { - | _____________________^ +LL | let _ = x.clone().map(|(x, y)| { + | ______________________^ LL | | return (x, y); LL | | }); | |______^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:34:21 + --> $DIR/map_identity.rs:34:22 | -LL | let _ = x.iter().map(|(x, y)| return (x, y)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = x.clone().map(|(x, y)| return (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:37:21 + --> $DIR/map_identity.rs:37:22 | -LL | let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` -error: aborting due to 10 previous errors +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:66:30 + | +LL | let _ = x.iter().copied().map(|(x, y)| (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: aborting due to 11 previous errors |
