Add new lint unneeded_struct_pattern

This commit is contained in:
Asuna 2024-09-27 02:58:14 +08:00
parent 2ddfc92ea2
commit 52abb8f9f0
9 changed files with 660 additions and 2 deletions

View file

@ -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,
},
}

View file

@ -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,
};
}

View file

@ -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,
};
}

View file

@ -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