about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorTimo <30553356+y21@users.noreply.github.com>2025-08-02 11:37:12 +0000
committerGitHub <noreply@github.com>2025-08-02 11:37:12 +0000
commitffcd12946e2d986e50174649e81463707ce7b8c3 (patch)
treeebac833342524fa8eb7504c3af2a85511e5f1225 /tests
parente42586d4954508da87280eb0770ba05d25c70a23 (diff)
parenteea4d6dc3cdc96cea7d4367726a6c0f18ab5a4ba (diff)
downloadrust-ffcd12946e2d986e50174649e81463707ce7b8c3.tar.gz
rust-ffcd12946e2d986e50174649e81463707ce7b8c3.zip
`{flat_,}map_identity`: recognize (tuple) struct de- and restructuring (#15261)
Follow-up of rust-lang/rust-clippy#15229, as described in
https://github.com/rust-lang/rust-clippy/pull/15229#issuecomment-3050279790
-- it turned out to be not that difficult after all!

changelog: [`map_identity`,`flat_map_identity`]: also recognize (tuple)
struct de- and resctructuring

r? @y21
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/map_identity.fixed64
-rw-r--r--tests/ui/map_identity.rs64
-rw-r--r--tests/ui/map_identity.stderr38
3 files changed, 163 insertions, 3 deletions
diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed
index b82d3e6d956..6c971ba6338 100644
--- a/tests/ui/map_identity.fixed
+++ b/tests/ui/map_identity.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::map_identity)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::disallowed_names)]
 
 fn main() {
     let x: [u16; 3] = [1, 2, 3];
@@ -99,3 +99,65 @@ fn issue15198() {
     let _ = x.iter().copied();
     //~^ map_identity
 }
+
+mod foo {
+    #[derive(Clone, Copy)]
+    pub struct Foo {
+        pub foo: u8,
+        pub bar: u8,
+    }
+
+    #[derive(Clone, Copy)]
+    pub struct Foo2(pub u8, pub u8);
+}
+use foo::{Foo, Foo2};
+
+struct Bar {
+    foo: u8,
+    bar: u8,
+}
+
+struct Bar2(u8, u8);
+
+fn structs() {
+    let x = [Foo { foo: 0, bar: 0 }];
+
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar });
+
+    // still lint with redundant field names
+    #[allow(clippy::redundant_field_names)]
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint with field order change
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo });
+}
+
+fn tuple_structs() {
+    let x = [Foo2(0, 0)];
+
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar));
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo));
+}
diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs
index c295bf87270..59dcfcda3b6 100644
--- a/tests/ui/map_identity.rs
+++ b/tests/ui/map_identity.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::map_identity)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::disallowed_names)]
 
 fn main() {
     let x: [u16; 3] = [1, 2, 3];
@@ -105,3 +105,65 @@ fn issue15198() {
     let _ = x.iter().copied().map(|[x, y]| [x, y]);
     //~^ map_identity
 }
+
+mod foo {
+    #[derive(Clone, Copy)]
+    pub struct Foo {
+        pub foo: u8,
+        pub bar: u8,
+    }
+
+    #[derive(Clone, Copy)]
+    pub struct Foo2(pub u8, pub u8);
+}
+use foo::{Foo, Foo2};
+
+struct Bar {
+    foo: u8,
+    bar: u8,
+}
+
+struct Bar2(u8, u8);
+
+fn structs() {
+    let x = [Foo { foo: 0, bar: 0 }];
+
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar });
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar });
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar });
+
+    // still lint with redundant field names
+    #[allow(clippy::redundant_field_names)]
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar });
+    //~^ map_identity
+
+    // still lint with field order change
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo });
+    //~^ map_identity
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo });
+}
+
+fn tuple_structs() {
+    let x = [Foo2(0, 0)];
+
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar));
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar));
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar));
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo));
+}
diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr
index 9b624a0dc75..a50c0d6b87b 100644
--- a/tests/ui/map_identity.stderr
+++ b/tests/ui/map_identity.stderr
@@ -93,5 +93,41 @@ error: unnecessary map of the identity function
 LL |     let _ = x.iter().copied().map(|[x, y]| [x, y]);
    |                              ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
 
-error: aborting due to 14 previous errors
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:131:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:135:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:143:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:147:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:157:26
+   |
+LL |     let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:161:26
+   |
+LL |     let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: aborting due to 20 previous errors