Description
As suggested in the non_exhaustive RFC, when using non-exhaustive enums and structs in patterns, the lint would warn the user for missing variants or fields despite having a wildcard arm or a rest pattern.
This can be useful when new fields/variants are added by the upstream crate so that they don't go unnoticed.
Enums
Given the following definition
#[non_exhaustive]
pub enum E {
First,
Second,
Third,
}
The following use should be linted:
match e {
E::First => {}
E::Second => {}
_ => {}
}
Structs
Given the following definition
#[derive(Default)]
#[non_exhaustive]
pub struct S {
pub a: i32,
pub b: i32,
pub c: i32,
}
The following cases should be linted
let S { a: _, b: _, .. } = S::default();
match S::default() {
S { a: 42, b: 21, .. } => {}
S { a: _, b: _, .. } => {}
}
if let S { a: 42, b: _, .. } = S::default() {}
while let S { a: 42, b: _, .. } = S::default() {
break;
}
let v = vec![S::default()];
for S { a: _, b: _, .. } in v {}
In addition to let destructuring in function parameters
pub fn take_s(S { a, b, .. }: S) -> (i32, i32) {
(a, b)
}
A struct variant of an enum should be linted in the same cases if it's the only variant of the enum. If it's not the only member, it can be linted only in the match, if let and while let cases.
Tuple structs
Tuple structs can't be used in patterns if there are private fields using the T()
syntax, but the T{0: _, 1: _}
syntax can be used an so it should be linted like with structs.
Given the following definition
#[derive(Default)]
#[non_exhaustive]
pub struct T(pub i32, pub i32, pub i32);
The following cases should be linted
let T { 0: _, 1: _, .. } = T::default();
match T::default() {
T { 0: 42, 1: 21, .. } => {}
T { 0: _, 1: _, .. } => {}
}
if let T { 0: 42, 1: _, .. } = T::default() {}
while let T { 0: 42, 1: _, .. } = T::default() {
break;
}
let v = vec![T::default()];
for T { 0: _, 1: _, .. } in v {}
In addition to let destructuring in function parameters
pub fn take_t(T { 0: a, 1: b, .. }: T) -> (i32, i32) {
(a, b)
}
Notes
- The non-exhaustive data structure must come from another crate (otherwise the restrictions associated to non-exhaustive data structures do not apply).
- The lint should not trigger if only the rest pattern is used, so at least one field should be used in the pattern.
- The lint should be allow-by-default.
- Although described in the RFC, FRU is not supported currently so constructing a non-exhaustive struct is not possible.
- Unit structs are not candidates for this lint because new fields can't be added.