about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorAsuna <SpriteOvO@gmail.com>2024-09-27 02:58:14 +0800
committerAsuna <SpriteOvO@gmail.com>2024-12-15 03:59:11 +0100
commit52abb8f9f0009ac951cee312fb97592bd18ab258 (patch)
tree78bcdc72e4332ea38b75f9455ba65bc072cebe13 /tests
parent2ddfc92ea2a0a9b63e7d90f38b141667378db49e (diff)
downloadrust-52abb8f9f0009ac951cee312fb97592bd18ab258.tar.gz
rust-52abb8f9f0009ac951cee312fb97592bd18ab258.zip
Add new lint `unneeded_struct_pattern`
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/auxiliary/non-exhaustive-enum.rs21
-rw-r--r--tests/ui/unneeded_struct_pattern.fixed177
-rw-r--r--tests/ui/unneeded_struct_pattern.rs177
-rw-r--r--tests/ui/unneeded_struct_pattern.stderr203
4 files changed, 578 insertions, 0 deletions
diff --git a/tests/ui/auxiliary/non-exhaustive-enum.rs b/tests/ui/auxiliary/non-exhaustive-enum.rs
index 420232f9f8d..e3205193cce 100644
--- a/tests/ui/auxiliary/non-exhaustive-enum.rs
+++ b/tests/ui/auxiliary/non-exhaustive-enum.rs
@@ -6,3 +6,24 @@ pub enum ErrorKind {
     #[doc(hidden)]
     Uncategorized,
 }
+
+#[non_exhaustive]
+pub enum ExtNonExhaustiveEnum {
+    Unit,
+    Tuple(i32),
+    Struct { field: i32 },
+}
+
+pub enum ExtNonExhaustiveVariant {
+    ExhaustiveUnit,
+    #[non_exhaustive]
+    Unit,
+    #[non_exhaustive]
+    Tuple(i32),
+    #[non_exhaustive]
+    StructNoField {},
+    #[non_exhaustive]
+    Struct {
+        field: i32,
+    },
+}
diff --git a/tests/ui/unneeded_struct_pattern.fixed b/tests/ui/unneeded_struct_pattern.fixed
new file mode 100644
index 00000000000..5bd269896a6
--- /dev/null
+++ b/tests/ui/unneeded_struct_pattern.fixed
@@ -0,0 +1,177 @@
+//@aux-build:non-exhaustive-enum.rs
+#![allow(
+    clippy::manual_unwrap_or_default,
+    clippy::manual_unwrap_or,
+    clippy::redundant_pattern_matching
+)]
+#![warn(clippy::unneeded_struct_pattern)]
+
+extern crate non_exhaustive_enum;
+use non_exhaustive_enum::*;
+
+fn noop() {}
+
+fn main() {
+    match Some(114514) {
+        Some(v) => v,
+        None => 0,
+    };
+
+    match Some(1919810) {
+        Some(v) => v,
+        None => 0,
+    };
+
+    match Some(123456) {
+        Some(v) => v,
+        None => 0,
+    };
+
+    match Some(Some(123456)) {
+        Some(Some(v)) => v,
+        Some(None) => 0,
+        None => 0,
+    };
+
+    if let None = Some(0) {}
+    if let None = Some(0) {}
+    if let Some(None) = Some(Some(0)) {}
+    let None = Some(0) else { panic!() };
+    let None = Some(0) else { panic!() };
+    let Some(None) = Some(Some(0)) else { panic!() };
+
+    enum Custom {
+        HasFields {
+            field: i32,
+        },
+        HasBracketsNoFields {},
+        NoBrackets,
+        #[non_exhaustive]
+        NoBracketsNonExhaustive,
+        Init,
+    };
+
+    match Custom::Init {
+        Custom::HasFields { field: value } => value,
+        Custom::HasBracketsNoFields {} => 0,
+        Custom::NoBrackets => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::HasFields { field: value } => value,
+        Custom::HasBracketsNoFields { .. } => 0,
+        Custom::NoBrackets => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::NoBrackets if true => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::NoBrackets | Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    if let Custom::HasFields { field: value } = Custom::Init {
+        noop();
+    }
+    if let Custom::HasBracketsNoFields {} = Custom::Init {
+        noop();
+    }
+    if let Custom::HasBracketsNoFields { .. } = Custom::Init {
+        noop();
+    }
+    if let Custom::NoBrackets = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBrackets = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBrackets | Custom::NoBracketsNonExhaustive = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBracketsNonExhaustive = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBracketsNonExhaustive = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+
+    let Custom::HasFields { field: value } = Custom::Init else {
+        panic!()
+    };
+
+    let Custom::HasBracketsNoFields {} = Custom::Init else {
+        panic!()
+    };
+
+    let Custom::HasBracketsNoFields { .. } = Custom::Init else {
+        panic!()
+    };
+    let Custom::NoBrackets = Custom::Init else { panic!() }; //~ ERROR: struct pattern is not needed for a unit variant
+
+    let Custom::NoBrackets = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+    let Custom::NoBracketsNonExhaustive = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+    let Custom::NoBracketsNonExhaustive = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+
+    enum Refutable {
+        Variant,
+    }
+
+    fn pat_in_fn_param_1(Refutable::Variant: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant
+    fn pat_in_fn_param_2(Refutable::Variant: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant
+
+    for Refutable::Variant in [] {} //~ ERROR: struct pattern is not needed for a unit variant
+    for Refutable::Variant in [] {} //~ ERROR: struct pattern is not needed for a unit variant
+}
+
+fn external_crate() {
+    use ExtNonExhaustiveVariant::*;
+
+    match ExhaustiveUnit {
+        // Expected
+        ExhaustiveUnit => 0,
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        // Exhaustive variant
+        ExhaustiveUnit => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        // Exhaustive variant
+        ExhaustiveUnit => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        ExhaustiveUnit => 0,
+        // vvvvv Non-exhaustive variants, should all be ignored
+        Unit { .. } => 0,
+        Tuple { 0: field, .. } => field,
+        StructNoField { .. } => 0,
+        Struct { field, .. } => field,
+        _ => 0,
+    };
+}
diff --git a/tests/ui/unneeded_struct_pattern.rs b/tests/ui/unneeded_struct_pattern.rs
new file mode 100644
index 00000000000..c7658617ad3
--- /dev/null
+++ b/tests/ui/unneeded_struct_pattern.rs
@@ -0,0 +1,177 @@
+//@aux-build:non-exhaustive-enum.rs
+#![allow(
+    clippy::manual_unwrap_or_default,
+    clippy::manual_unwrap_or,
+    clippy::redundant_pattern_matching
+)]
+#![warn(clippy::unneeded_struct_pattern)]
+
+extern crate non_exhaustive_enum;
+use non_exhaustive_enum::*;
+
+fn noop() {}
+
+fn main() {
+    match Some(114514) {
+        Some(v) => v,
+        None {} => 0,
+    };
+
+    match Some(1919810) {
+        Some(v) => v,
+        None { .. } => 0,
+    };
+
+    match Some(123456) {
+        Some(v) => v,
+        None => 0,
+    };
+
+    match Some(Some(123456)) {
+        Some(Some(v)) => v,
+        Some(None {}) => 0,
+        None {} => 0,
+    };
+
+    if let None {} = Some(0) {}
+    if let None { .. } = Some(0) {}
+    if let Some(None {}) = Some(Some(0)) {}
+    let None {} = Some(0) else { panic!() };
+    let None { .. } = Some(0) else { panic!() };
+    let Some(None {}) = Some(Some(0)) else { panic!() };
+
+    enum Custom {
+        HasFields {
+            field: i32,
+        },
+        HasBracketsNoFields {},
+        NoBrackets,
+        #[non_exhaustive]
+        NoBracketsNonExhaustive,
+        Init,
+    };
+
+    match Custom::Init {
+        Custom::HasFields { field: value } => value,
+        Custom::HasBracketsNoFields {} => 0,
+        Custom::NoBrackets {} => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        Custom::NoBracketsNonExhaustive {} => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::HasFields { field: value } => value,
+        Custom::HasBracketsNoFields { .. } => 0,
+        Custom::NoBrackets { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        Custom::NoBracketsNonExhaustive { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::NoBrackets {} if true => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match Custom::Init {
+        Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    if let Custom::HasFields { field: value } = Custom::Init {
+        noop();
+    }
+    if let Custom::HasBracketsNoFields {} = Custom::Init {
+        noop();
+    }
+    if let Custom::HasBracketsNoFields { .. } = Custom::Init {
+        noop();
+    }
+    if let Custom::NoBrackets {} = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBrackets { .. } = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBracketsNonExhaustive {} = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+    if let Custom::NoBracketsNonExhaustive { .. } = Custom::Init {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        noop();
+    }
+
+    let Custom::HasFields { field: value } = Custom::Init else {
+        panic!()
+    };
+
+    let Custom::HasBracketsNoFields {} = Custom::Init else {
+        panic!()
+    };
+
+    let Custom::HasBracketsNoFields { .. } = Custom::Init else {
+        panic!()
+    };
+    let Custom::NoBrackets {} = Custom::Init else { panic!() }; //~ ERROR: struct pattern is not needed for a unit variant
+
+    let Custom::NoBrackets { .. } = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+    let Custom::NoBracketsNonExhaustive {} = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+    let Custom::NoBracketsNonExhaustive { .. } = Custom::Init else {
+        //~^ ERROR: struct pattern is not needed for a unit variant
+        panic!()
+    };
+
+    enum Refutable {
+        Variant,
+    }
+
+    fn pat_in_fn_param_1(Refutable::Variant {}: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant
+    fn pat_in_fn_param_2(Refutable::Variant { .. }: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant
+
+    for Refutable::Variant {} in [] {} //~ ERROR: struct pattern is not needed for a unit variant
+    for Refutable::Variant { .. } in [] {} //~ ERROR: struct pattern is not needed for a unit variant
+}
+
+fn external_crate() {
+    use ExtNonExhaustiveVariant::*;
+
+    match ExhaustiveUnit {
+        // Expected
+        ExhaustiveUnit => 0,
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        // Exhaustive variant
+        ExhaustiveUnit { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        // Exhaustive variant
+        ExhaustiveUnit {} => 0, //~ ERROR: struct pattern is not needed for a unit variant
+        _ => 0,
+    };
+
+    match ExhaustiveUnit {
+        ExhaustiveUnit => 0,
+        // vvvvv Non-exhaustive variants, should all be ignored
+        Unit { .. } => 0,
+        Tuple { 0: field, .. } => field,
+        StructNoField { .. } => 0,
+        Struct { field, .. } => field,
+        _ => 0,
+    };
+}
diff --git a/tests/ui/unneeded_struct_pattern.stderr b/tests/ui/unneeded_struct_pattern.stderr
new file mode 100644
index 00000000000..3a7f5958380
--- /dev/null
+++ b/tests/ui/unneeded_struct_pattern.stderr
@@ -0,0 +1,203 @@
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:17:13
+   |
+LL |         None {} => 0,
+   |             ^^^ help: remove the struct pattern
+   |
+   = note: `-D clippy::unneeded-struct-pattern` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::unneeded_struct_pattern)]`
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:22:13
+   |
+LL |         None { .. } => 0,
+   |             ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:32:18
+   |
+LL |         Some(None {}) => 0,
+   |                  ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:33:13
+   |
+LL |         None {} => 0,
+   |             ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:36:16
+   |
+LL |     if let None {} = Some(0) {}
+   |                ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:37:16
+   |
+LL |     if let None { .. } = Some(0) {}
+   |                ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:38:21
+   |
+LL |     if let Some(None {}) = Some(Some(0)) {}
+   |                     ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:39:13
+   |
+LL |     let None {} = Some(0) else { panic!() };
+   |             ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:40:13
+   |
+LL |     let None { .. } = Some(0) else { panic!() };
+   |             ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:41:18
+   |
+LL |     let Some(None {}) = Some(Some(0)) else { panic!() };
+   |                  ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:57:27
+   |
+LL |         Custom::NoBrackets {} => 0,
+   |                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:58:40
+   |
+LL |         Custom::NoBracketsNonExhaustive {} => 0,
+   |                                        ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:65:27
+   |
+LL |         Custom::NoBrackets { .. } => 0,
+   |                           ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:66:40
+   |
+LL |         Custom::NoBracketsNonExhaustive { .. } => 0,
+   |                                        ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:71:27
+   |
+LL |         Custom::NoBrackets {} if true => 0,
+   |                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:76:27
+   |
+LL |         Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0,
+   |                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:76:64
+   |
+LL |         Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0,
+   |                                                                ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:89:30
+   |
+LL |     if let Custom::NoBrackets {} = Custom::Init {
+   |                              ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:93:30
+   |
+LL |     if let Custom::NoBrackets { .. } = Custom::Init {
+   |                              ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:97:30
+   |
+LL |     if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init {
+   |                              ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:97:67
+   |
+LL |     if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init {
+   |                                                                   ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:101:43
+   |
+LL |     if let Custom::NoBracketsNonExhaustive {} = Custom::Init {
+   |                                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:105:43
+   |
+LL |     if let Custom::NoBracketsNonExhaustive { .. } = Custom::Init {
+   |                                           ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:121:27
+   |
+LL |     let Custom::NoBrackets {} = Custom::Init else { panic!() };
+   |                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:123:27
+   |
+LL |     let Custom::NoBrackets { .. } = Custom::Init else {
+   |                           ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:127:40
+   |
+LL |     let Custom::NoBracketsNonExhaustive {} = Custom::Init else {
+   |                                        ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:131:40
+   |
+LL |     let Custom::NoBracketsNonExhaustive { .. } = Custom::Init else {
+   |                                        ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:140:44
+   |
+LL |     fn pat_in_fn_param_1(Refutable::Variant {}: Refutable) {}
+   |                                            ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:141:44
+   |
+LL |     fn pat_in_fn_param_2(Refutable::Variant { .. }: Refutable) {}
+   |                                            ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:143:27
+   |
+LL |     for Refutable::Variant {} in [] {}
+   |                           ^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:144:27
+   |
+LL |     for Refutable::Variant { .. } in [] {}
+   |                           ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:158:23
+   |
+LL |         ExhaustiveUnit { .. } => 0,
+   |                       ^^^^^^^ help: remove the struct pattern
+
+error: struct pattern is not needed for a unit variant
+  --> tests/ui/unneeded_struct_pattern.rs:164:23
+   |
+LL |         ExhaustiveUnit {} => 0,
+   |                       ^^^ help: remove the struct pattern
+
+error: aborting due to 33 previous errors
+