Skip to content

Commit 7f65cab

Browse files
committed
not_exhaustive_enough
1 parent 31ca816 commit 7f65cab

File tree

5 files changed

+160
-144
lines changed

5 files changed

+160
-144
lines changed

clippy_lints/src/not_exhaustive_enough.rs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ impl<'tcx> LateLintPass<'tcx> for NotExhaustiveEnough {
4747
if_chain! {
4848
if let PatKind::Struct(_, ref field_pats, ref rest_pat) = &pat.kind;
4949
if let ty::Adt(adt_def, _) = cx.typeck_results().pat_ty(pat).kind();
50-
if adt_def.is_struct();
5150
if is_struct_not_exhaustive(adt_def);
5251
if *rest_pat;
5352
if !field_pats.is_empty();
@@ -96,18 +95,17 @@ fn check_struct_pat<'tcx>(
9695
field_defs: &[ty::FieldDef],
9796
) {
9897
let missing_fields = get_missing_fields(field_pats, field_defs);
99-
if missing_fields.len() > 0 {
100-
let mut suggestions = vec![];
101-
suggestions = missing_fields.iter().map(|v| v.to_owned() + ": _").collect();
102-
span_lint_and_sugg(
103-
cx,
104-
NOT_EXHAUSTIVE_ENOUGH,
105-
pat.span,
106-
"struct match is not exhaustive enough",
107-
"try adding missing fields",
108-
suggestions.join(" , "),
109-
Applicability::MaybeIncorrect,
110-
);
98+
if !missing_fields.is_empty() {
99+
let suggestions: Vec<String> = missing_fields.iter().map(|v| v.to_owned() + ": _").collect();
100+
span_lint_and_sugg(
101+
cx,
102+
NOT_EXHAUSTIVE_ENOUGH,
103+
pat.span,
104+
"struct match is not exhaustive enough",
105+
"try adding missing fields",
106+
suggestions.join(" , "),
107+
Applicability::MaybeIncorrect,
108+
);
111109
}
112110
}
113111

@@ -122,16 +120,12 @@ fn get_missing_variants<'tcx>(cx: &LateContext<'tcx>, arms: &[Arm<'_>], e: &'tcx
122120
for arm in arms {
123121
if let PatKind::Path(ref path) = arm.pat.kind {
124122
if let QPath::Resolved(_, p) = path {
125-
println!("{:?}", path);
126123
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
127124
}
128-
} else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind {
129-
if let QPath::Resolved(_, p) = path {
130-
let is_pattern_exhaustive =
131-
|pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None));
132-
if patterns.iter().all(is_pattern_exhaustive) {
133-
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
134-
}
125+
} else if let PatKind::TupleStruct(QPath::Resolved(_, p), ref patterns, ..) = arm.pat.kind {
126+
let is_pattern_exhaustive = |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None));
127+
if patterns.iter().all(is_pattern_exhaustive) {
128+
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
135129
}
136130
}
137131
}

clippy_lints/src/types.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,9 +1104,7 @@ fn is_empty_block(expr: &Expr<'_>) -> bool {
11041104
expr.kind,
11051105
ExprKind::Block(
11061106
Block {
1107-
stmts: &[],
1108-
expr: None,
1109-
..
1107+
stmts: &[], expr: None, ..
11101108
},
11111109
_,
11121110
)

tests/ui/auxiliary/not_exhaustive_enough_helper.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
#[non_exhaustive]
42
pub enum AnotherCrateEnum {
53
AFirst,

tests/ui/not_exhaustive_enough.rs

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,116 +9,124 @@ extern crate not_exhaustive_enough_helper;
99
use not_exhaustive_enough_helper::{AnotherCrateEnum, AnotherCrateStruct, TPrivateField};
1010

1111
#[non_exhaustive]
12-
pub enum E {
12+
pub enum DefaultEnum {
1313
First,
1414
Second,
1515
Third,
1616
}
1717

1818
#[non_exhaustive]
19-
pub enum K {
19+
pub enum DataEnum {
2020
First(String),
2121
Second(u32, u32),
22-
Third(String)
22+
Third(String),
2323
}
2424

25-
enum EF {
25+
pub enum StructVariantEnum1 {
2626
#[non_exhaustive]
27-
V{a: i32, b: i32}
27+
V { a: i32, b: i32 },
2828
}
2929

30-
enum F {
30+
pub enum StructVariantEnum2 {
3131
#[non_exhaustive]
32-
V{a: i32, b: i32},
33-
A{c: u32}
32+
V {
33+
a: i32,
34+
b: i32,
35+
},
36+
A {
37+
c: u32,
38+
},
3439
}
3540

3641
#[derive(Default)]
3742
#[non_exhaustive]
38-
pub struct S {
43+
pub struct DefaultStruct {
3944
pub a: i32,
4045
pub b: i32,
4146
pub c: i32,
4247
}
4348

4449
#[derive(Default)]
4550
#[non_exhaustive]
46-
pub struct T(pub i32, pub i32, pub i32);
47-
51+
pub struct DefaultTuple(pub i32, pub i32, pub i32);
4852

4953
fn main() {
5054
//////// Enum
5155

52-
let e = E::First;
56+
let default_enum = DefaultEnum::First;
5357

54-
let ef = EF::V{a: 1, b:2};
58+
let struct_variant_enum_1 = StructVariantEnum1::V { a: 1, b: 2 };
5559

56-
let f = F::V{a:1, b:2};
60+
let struct_variant_enum_2 = StructVariantEnum2::V { a: 1, b: 2 };
5761

58-
match e {
59-
E::First => {},
60-
E::Second => {},
62+
match default_enum {
63+
DefaultEnum::First => {},
64+
DefaultEnum::Second => {},
6165
_ => {},
6266
}
6367

64-
match ef {
65-
EF::V{a:_, ..} => {}
68+
match struct_variant_enum_1 {
69+
StructVariantEnum1::V { a: _, .. } => {},
6670
}
6771

68-
if let F::V{a:_, ..} = f {}
72+
match struct_variant_enum_2 {
73+
StructVariantEnum2::V { a: _, .. } => {},
74+
_ => {},
75+
}
6976

7077
//
78+
7179
let example = "Example".to_string();
72-
let k = K::First(example);
80+
let data_enum = DataEnum::First(example);
7381

74-
match k {
75-
K::First(..) => {},
76-
K::Second(..) => {},
82+
match data_enum {
83+
DataEnum::First(..) => {},
84+
DataEnum::Second(..) => {},
7785
_ => {},
7886
}
7987

8088
//////// Struct
8189

82-
let S { a: _, b: _, .. } = S::default();
90+
let DefaultStruct { a: _, b: _, .. } = DefaultStruct::default();
8391

84-
match S::default() {
85-
S { a: 42, b: 21, .. } => {},
86-
S { a: _, b: _, .. } => {},
92+
match DefaultStruct::default() {
93+
DefaultStruct { a: 42, b: 21, .. } => {},
94+
DefaultStruct { a: _, b: _, .. } => {},
8795
}
8896

89-
if let S { a: 42, b: _, .. } = S::default() {}
97+
if let DefaultStruct { a: 42, b: _, .. } = DefaultStruct::default() {}
9098

91-
let v = vec![S::default()];
99+
let v = vec![DefaultStruct::default()];
92100

93-
for S { a: _, b: _, .. } in v {}
101+
for DefaultStruct { a: _, b: _, .. } in v {}
94102

95-
while let S { a: 42, b: _, .. } = S::default() {
103+
while let DefaultStruct { a: 42, b: _, .. } = DefaultStruct::default() {
96104
break;
97105
}
98106

99-
pub fn take_s(S { a, b, .. }: S) -> (i32, i32) {
107+
pub fn take_s(DefaultStruct { a, b, .. }: DefaultStruct) -> (i32, i32) {
100108
(a, b)
101109
}
102110

103111
//////// Tuple Struct
104112

105-
let T { 0: _, 1: _, .. } = T::default();
113+
let DefaultTuple { 0: _, 1: _, .. } = DefaultTuple::default();
106114

107-
match T::default() {
108-
T { 0: 42, 1: 21, .. } => {},
109-
T { 0: _, 1: _, .. } => {},
115+
match DefaultTuple::default() {
116+
DefaultTuple { 0: 42, 1: 21, .. } => {},
117+
DefaultTuple { 0: _, 1: _, .. } => {},
110118
}
111119

112-
if let T { 0: 42, 1: _, .. } = T::default() {}
120+
if let DefaultTuple { 0: 42, 1: _, .. } = DefaultTuple::default() {}
113121

114-
let v = vec![T::default()];
115-
for T { 0: _, 1: _, .. } in v {}
122+
let default_tuple = vec![DefaultTuple::default()];
123+
for DefaultTuple { 0: _, 1: _, .. } in default_tuple {}
116124

117-
while let T { 0: 42, 1: _, .. } = T::default() {
125+
while let DefaultTuple { 0: 42, 1: _, .. } = DefaultTuple::default() {
118126
break;
119127
}
120128

121-
pub fn take_t(T { 0: _, 1: _, .. }: T) -> (i32, i32) {
129+
pub fn take_t(DefaultTuple { 0: _, 1: _, .. }: DefaultTuple) -> (i32, i32) {
122130
(0, 1)
123131
}
124132

@@ -132,8 +140,8 @@ fn main() {
132140
}
133141

134142
match TPrivateField::default() {
135-
TPrivateField {1: 21, .. } => {},
136-
_ => {}
143+
TPrivateField { 1: 21, .. } => {},
144+
_ => {},
137145
}
138146

139147
if let TPrivateField { 0: 42, 1: _, .. } = TPrivateField::default() {}

0 commit comments

Comments
 (0)