Add exhaustive_structs lint
This commit is contained in:
parent
09d4d49299
commit
8cb7e85006
@ -1939,6 +1939,7 @@ Released 2018-09-13
|
||||
[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
|
||||
[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
|
||||
[`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums
|
||||
[`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs
|
||||
[`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit
|
||||
[`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call
|
||||
[`expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_used
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::utils::{snippet_opt, span_lint_and_help, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
@ -10,7 +10,8 @@ declare_clippy_lint! {
|
||||
/// **What it does:** Warns on any exported `enum`s that are not tagged `#[non_exhaustive]`
|
||||
///
|
||||
/// **Why is this bad?** Exhaustive enums are typically fine, but a project which does
|
||||
/// not wish to make a stability commitment around enums may wish to disable them by default.
|
||||
/// not wish to make a stability commitment around exported enums may wish to
|
||||
/// disable them by default.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
@ -28,25 +29,62 @@ declare_clippy_lint! {
|
||||
/// enum Foo {
|
||||
/// Bar,
|
||||
/// Baz
|
||||
/// } /// ```
|
||||
/// }
|
||||
/// ```
|
||||
pub EXHAUSTIVE_ENUMS,
|
||||
restriction,
|
||||
"default lint description"
|
||||
"detects exported enums that have not been marked #[non_exhaustive]"
|
||||
}
|
||||
|
||||
declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS]);
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Warns on any exported `structs`s that are not tagged `#[non_exhaustive]`
|
||||
///
|
||||
/// **Why is this bad?** Exhaustive structs are typically fine, but a project which does
|
||||
/// not wish to make a stability commitment around exported structs may wish to
|
||||
/// disable them by default.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// struct Foo {
|
||||
/// bar: u8,
|
||||
/// baz: String,
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// #[non_exhaustive]
|
||||
/// struct Foo {
|
||||
/// bar: u8,
|
||||
/// baz: String,
|
||||
/// }
|
||||
/// ```
|
||||
pub EXHAUSTIVE_STRUCTS,
|
||||
restriction,
|
||||
"detects exported structs that have not been marked #[non_exhaustive]"
|
||||
}
|
||||
|
||||
declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]);
|
||||
|
||||
impl LateLintPass<'_> for ExhaustiveItems {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if_chain! {
|
||||
if let ItemKind::Enum(..) = item.kind;
|
||||
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
|
||||
if cx.access_levels.is_exported(item.hir_id);
|
||||
if !item.attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
|
||||
then {
|
||||
let lint = if let ItemKind::Enum(..) = item.kind {
|
||||
EXHAUSTIVE_ENUMS
|
||||
} else {
|
||||
EXHAUSTIVE_STRUCTS
|
||||
};
|
||||
|
||||
if let Some(snippet) = snippet_opt(cx, item.span) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
EXHAUSTIVE_ENUMS,
|
||||
lint,
|
||||
item.span,
|
||||
"enums should not be exhaustive",
|
||||
"try adding #[non_exhaustive]",
|
||||
@ -56,7 +94,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
||||
} else {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
EXHAUSTIVE_ENUMS,
|
||||
lint,
|
||||
item.span,
|
||||
"enums should not be exhaustive",
|
||||
None,
|
||||
|
@ -613,6 +613,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
&excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
|
||||
&excessive_bools::STRUCT_EXCESSIVE_BOOLS,
|
||||
&exhaustive_items::EXHAUSTIVE_ENUMS,
|
||||
&exhaustive_items::EXHAUSTIVE_STRUCTS,
|
||||
&exit::EXIT,
|
||||
&explicit_write::EXPLICIT_WRITE,
|
||||
&fallible_impl_from::FALLIBLE_IMPL_FROM,
|
||||
@ -1250,6 +1251,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&dbg_macro::DBG_MACRO),
|
||||
LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE),
|
||||
LintId::of(&exhaustive_items::EXHAUSTIVE_ENUMS),
|
||||
LintId::of(&exhaustive_items::EXHAUSTIVE_STRUCTS),
|
||||
LintId::of(&exit::EXIT),
|
||||
LintId::of(&float_literal::LOSSY_FLOAT_LITERAL),
|
||||
LintId::of(&implicit_return::IMPLICIT_RETURN),
|
||||
|
@ -1,42 +1,72 @@
|
||||
// run-rustfix
|
||||
|
||||
#![deny(clippy::exhaustive_enums)]
|
||||
#![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
|
||||
#![allow(unused)]
|
||||
|
||||
fn main() {
|
||||
// nop
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub mod enums {
|
||||
#[non_exhaustive]
|
||||
pub enum Exhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub enum NonExhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
enum ExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
enum NonExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
}
|
||||
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub enum NonExhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
pub mod structs {
|
||||
#[non_exhaustive]
|
||||
pub struct Exhaustive {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
enum ExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub struct NonExhaustive {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
enum NonExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
// no warning, private
|
||||
struct ExhaustivePrivate {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
struct NonExhaustivePrivate {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +1,70 @@
|
||||
// run-rustfix
|
||||
|
||||
#![deny(clippy::exhaustive_enums)]
|
||||
#![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
|
||||
#![allow(unused)]
|
||||
|
||||
fn main() {
|
||||
// nop
|
||||
}
|
||||
|
||||
pub enum Exhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
pub mod enums {
|
||||
pub enum Exhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub enum NonExhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
enum ExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
enum NonExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
}
|
||||
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub enum NonExhaustive {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
pub mod structs {
|
||||
pub struct Exhaustive {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
enum ExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
}
|
||||
// no warning, already non_exhaustive
|
||||
#[non_exhaustive]
|
||||
pub struct NonExhaustive {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
enum NonExhaustivePrivate {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
Quux(String),
|
||||
// no warning, private
|
||||
struct ExhaustivePrivate {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// no warning, private
|
||||
#[non_exhaustive]
|
||||
struct NonExhaustivePrivate {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,46 @@
|
||||
error: enums should not be exhaustive
|
||||
--> $DIR/exhaustive_items.rs:10:1
|
||||
--> $DIR/exhaustive_items.rs:11:5
|
||||
|
|
||||
LL | / pub enum Exhaustive {
|
||||
LL | | Foo,
|
||||
LL | | Bar,
|
||||
LL | | Baz,
|
||||
LL | | Quux(String),
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | / pub enum Exhaustive {
|
||||
LL | | Foo,
|
||||
LL | | Bar,
|
||||
LL | | Baz,
|
||||
LL | | Quux(String),
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/exhaustive_items.rs:3:9
|
||||
--> $DIR/exhaustive_items.rs:3:35
|
||||
|
|
||||
LL | #![deny(clippy::exhaustive_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: try adding #[non_exhaustive]
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
LL | #[non_exhaustive]
|
||||
LL | pub enum Exhaustive {
|
||||
LL | Foo,
|
||||
LL | Bar,
|
||||
LL | Baz,
|
||||
LL | Quux(String),
|
||||
LL | Foo,
|
||||
LL | Bar,
|
||||
LL | Baz,
|
||||
LL | Quux(String),
|
||||
...
|
||||
|
||||
error: aborting due to previous error
|
||||
error: enums should not be exhaustive
|
||||
--> $DIR/exhaustive_items.rs:46:5
|
||||
|
|
||||
LL | / pub struct Exhaustive {
|
||||
LL | | foo: u8,
|
||||
LL | | bar: String,
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try adding #[non_exhaustive]
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
LL | pub struct Exhaustive {
|
||||
LL | foo: u8,
|
||||
LL | bar: String,
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user