about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAda Alakbarova <ada.alakbarova@proton.me>2025-07-25 08:50:20 +0200
committerAda Alakbarova <ada.alakbarova@proton.me>2025-08-22 15:11:47 +0200
commit0d479c19e875918a6c5248f031fa50cf0997af85 (patch)
tree68578ec1d9fffb859a5191012b40a425e6a80663
parent877967959ae8da9814df4f2614971f4d784bf53f (diff)
downloadrust-0d479c19e875918a6c5248f031fa50cf0997af85.tar.gz
rust-0d479c19e875918a6c5248f031fa50cf0997af85.zip
fix: `unnested_or_patterns` FP on structs with only shorthand field pats
-rw-r--r--clippy_lints/src/unnested_or_patterns.rs6
-rw-r--r--tests/ui/unnested_or_patterns.fixed25
-rw-r--r--tests/ui/unnested_or_patterns.rs25
-rw-r--r--tests/ui/unnested_or_patterns.stderr54
4 files changed, 80 insertions, 30 deletions
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 8b278d98a30..f3410c98973 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -326,7 +326,11 @@ fn extend_with_struct_pat(
                     if idx_1 == idx {
                         // In the case of `k`, we merely require identical field names
                         // so that we will transform into `ident_k: p1_k | p2_k`.
-                        let pos = fps2.iter().position(|fp2| eq_id(fp1.ident, fp2.ident));
+                        let pos = fps2.iter().position(|fp2| {
+                            // Avoid `Foo { bar } | Foo { bar }` => `Foo { bar | bar }`
+                            !(fp1.is_shorthand && fp2.is_shorthand)
+                                && eq_id(fp1.ident, fp2.ident)
+                        });
                         pos_in_2.set(pos);
                         pos.is_some()
                     } else {
diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed
index 2081772d06b..339d4a95084 100644
--- a/tests/ui/unnested_or_patterns.fixed
+++ b/tests/ui/unnested_or_patterns.fixed
@@ -9,6 +9,11 @@
 )]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
 
+struct S {
+    x: u8,
+    y: u8,
+}
+
 fn main() {
     // Should be ignored by this lint, as nesting requires more characters.
     if let &0 | &2 = &0 {}
@@ -45,10 +50,6 @@ fn main() {
     //~^ unnested_or_patterns
     if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {}
     //~^ unnested_or_patterns
-    struct S {
-        x: u8,
-        y: u8,
-    }
     if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {}
     //~^ unnested_or_patterns
     if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
@@ -77,3 +78,19 @@ mod issue9952 {
     fn or_in_param((x | x | x): i32) {}
     //~^ unnested_or_patterns
 }
+
+fn issue15219() {
+    struct Foo {
+        x: u8,
+    }
+
+    // the original repro
+    if let Foo { x } | Foo { x } = (Foo { x: 0 }) {}
+
+    // also works with more fields
+    if let S { x, y } | S { x, y } = (S { x: 0, y: 0 }) {}
+
+    // `y` not triggering the lint doesn't stop the `x` from getting flagged
+    if let S { y, x: 0 | 1 } = (S { x: 0, y: 1 }) {}
+    //~^ unnested_or_patterns
+}
diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs
index 6bf8fce3661..f5c99183b0c 100644
--- a/tests/ui/unnested_or_patterns.rs
+++ b/tests/ui/unnested_or_patterns.rs
@@ -9,6 +9,11 @@
 )]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
 
+struct S {
+    x: u8,
+    y: u8,
+}
+
 fn main() {
     // Should be ignored by this lint, as nesting requires more characters.
     if let &0 | &2 = &0 {}
@@ -45,10 +50,6 @@ fn main() {
     //~^ unnested_or_patterns
     if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {}
     //~^ unnested_or_patterns
-    struct S {
-        x: u8,
-        y: u8,
-    }
     if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
     //~^ unnested_or_patterns
     if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
@@ -77,3 +78,19 @@ mod issue9952 {
     fn or_in_param((x | (x | x)): i32) {}
     //~^ unnested_or_patterns
 }
+
+fn issue15219() {
+    struct Foo {
+        x: u8,
+    }
+
+    // the original repro
+    if let Foo { x } | Foo { x } = (Foo { x: 0 }) {}
+
+    // also works with more fields
+    if let S { x, y } | S { x, y } = (S { x: 0, y: 0 }) {}
+
+    // `y` not triggering the lint doesn't stop the `x` from getting flagged
+    if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
+    //~^ unnested_or_patterns
+}
diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr
index c805dc992b1..d2b617c322c 100644
--- a/tests/ui/unnested_or_patterns.stderr
+++ b/tests/ui/unnested_or_patterns.stderr
@@ -1,5 +1,5 @@
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:16:12
+  --> tests/ui/unnested_or_patterns.rs:21:12
    |
 LL |     if let box 0 | box 2 = Box::new(0) {}
    |            ^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL +     if let box (0 | 2) = Box::new(0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:18:12
+  --> tests/ui/unnested_or_patterns.rs:23:12
    |
 LL |     if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL +     if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:21:12
+  --> tests/ui/unnested_or_patterns.rs:26:12
    |
 LL |     if let Some(1) | C0 | Some(2) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL +     if let Some(1 | 2) | C0 = None {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:23:12
+  --> tests/ui/unnested_or_patterns.rs:28:12
    |
 LL |     if let &mut 0 | &mut 2 = &mut 0 {}
    |            ^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL +     if let &mut (0 | 2) = &mut 0 {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:25:12
+  --> tests/ui/unnested_or_patterns.rs:30:12
    |
 LL |     if let x @ 0 | x @ 2 = 0 {}
    |            ^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL +     if let x @ (0 | 2) = 0 {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:27:12
+  --> tests/ui/unnested_or_patterns.rs:32:12
    |
 LL |     if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL +     if let (0, 1 | 2 | 3) = (0, 0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:29:12
+  --> tests/ui/unnested_or_patterns.rs:34:12
    |
 LL |     if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -85,7 +85,7 @@ LL +     if let (1 | 2 | 3, 0) = (0, 0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:31:12
+  --> tests/ui/unnested_or_patterns.rs:36:12
    |
 LL |     if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -97,7 +97,7 @@ LL +     if let (x, ..) | (x, 1 | 2) = (0, 1) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:33:12
+  --> tests/ui/unnested_or_patterns.rs:38:12
    |
 LL |     if let [0] | [1] = [0] {}
    |            ^^^^^^^^^
@@ -109,7 +109,7 @@ LL +     if let [0 | 1] = [0] {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:35:12
+  --> tests/ui/unnested_or_patterns.rs:40:12
    |
 LL |     if let [x, 0] | [x, 1] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^
@@ -121,7 +121,7 @@ LL +     if let [x, 0 | 1] = [0, 1] {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:37:12
+  --> tests/ui/unnested_or_patterns.rs:42:12
    |
 LL |     if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -133,7 +133,7 @@ LL +     if let [x, 0 | 1 | 2] = [0, 1] {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:39:12
+  --> tests/ui/unnested_or_patterns.rs:44:12
    |
 LL |     if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL +     if let [x, ..] | [x, 1 | 2] = [0, 1] {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:42:12
+  --> tests/ui/unnested_or_patterns.rs:47:12
    |
 LL |     if let TS(0, x) | TS(1, x) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@ LL +     if let TS(0 | 1, x) = TS(0, 0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:44:12
+  --> tests/ui/unnested_or_patterns.rs:49:12
    |
 LL |     if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -169,7 +169,7 @@ LL +     if let TS(1 | 2 | 3, 0) = TS(0, 0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:46:12
+  --> tests/ui/unnested_or_patterns.rs:51:12
    |
 LL |     if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -181,7 +181,7 @@ LL +     if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:52:12
+  --> tests/ui/unnested_or_patterns.rs:53:12
    |
 LL |     if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL +     if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:64:12
+  --> tests/ui/unnested_or_patterns.rs:65:12
    |
 LL |     if let [1] | [53] = [0] {}
    |            ^^^^^^^^^^
@@ -205,7 +205,7 @@ LL +     if let [1 | 53] = [0] {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:70:13
+  --> tests/ui/unnested_or_patterns.rs:71:13
    |
 LL |         let (0 | (1 | _)) = 0;
    |             ^^^^^^^^^^^^^
@@ -217,7 +217,7 @@ LL +         let (0 | 1 | _) = 0;
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:73:16
+  --> tests/ui/unnested_or_patterns.rs:74:16
    |
 LL |         if let (0 | (1 | _)) = 0 {}
    |                ^^^^^^^^^^^^^
@@ -229,7 +229,7 @@ LL +         if let (0 | 1 | _) = 0 {}
    |
 
 error: unnested or-patterns
-  --> tests/ui/unnested_or_patterns.rs:77:20
+  --> tests/ui/unnested_or_patterns.rs:78:20
    |
 LL |     fn or_in_param((x | (x | x)): i32) {}
    |                    ^^^^^^^^^^^^^
@@ -240,5 +240,17 @@ LL -     fn or_in_param((x | (x | x)): i32) {}
 LL +     fn or_in_param((x | x | x): i32) {}
    |
 
-error: aborting due to 20 previous errors
+error: unnested or-patterns
+  --> tests/ui/unnested_or_patterns.rs:94:12
+   |
+LL |     if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: nest the patterns
+   |
+LL -     if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
+LL +     if let S { y, x: 0 | 1 } = (S { x: 0, y: 1 }) {}
+   |
+
+error: aborting due to 21 previous errors