]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/manual_non_exhaustive.rs
Merge commit '4911ab124c481430672a3833b37075e6435ec34d' into clippyup
[rust.git] / clippy_lints / src / manual_non_exhaustive.rs
index f3b8902e26f672f4df92b63f07da040c67734b44..91849e748878f645b6453e1571cf8357f0fab61f 100644 (file)
@@ -1,11 +1,14 @@
-use crate::utils::{snippet_opt, span_lint_and_then};
+use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
 use if_chain::if_chain;
 use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
 use rustc_attr as attr;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::Span;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{sym, Span};
+
+const MANUAL_NON_EXHAUSTIVE_MSRV: RustcVersion = RustcVersion::new(1, 40, 0);
 
 declare_clippy_lint! {
     /// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
     "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
 }
 
-declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
+#[derive(Clone)]
+pub struct ManualNonExhaustive {
+    msrv: Option<RustcVersion>,
+}
+
+impl ManualNonExhaustive {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
 
 impl EarlyLintPass for ManualNonExhaustive {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
+            return;
+        }
+
         match &item.kind {
             ItemKind::Enum(def, _) => {
                 check_manual_non_exhaustive_enum(cx, item, &def.variants);
@@ -73,6 +92,8 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
             _ => {},
         }
     }
+
+    extract_msrv_attr!(EarlyContext);
 }
 
 fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
@@ -83,9 +104,9 @@ fn is_non_exhaustive_marker(variant: &Variant) -> bool {
     }
 
     fn is_doc_hidden(attr: &Attribute) -> bool {
-        attr.check_name(sym!(doc))
+        attr.has_name(sym::doc)
             && match attr.meta_item_list() {
-                Some(l) => attr::list_contains_name(&l, sym!(hidden)),
+                Some(l) => attr::list_contains_name(&l, sym::hidden),
                 None => false,
             }
     }
@@ -102,7 +123,7 @@ fn is_doc_hidden(attr: &Attribute) -> bool {
                 "this seems like a manual implementation of the non-exhaustive pattern",
                 |diag| {
                     if_chain! {
-                        if !attr::contains_name(&item.attrs, sym!(non_exhaustive));
+                        if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive));
                         let header_span = cx.sess.source_map().span_until_char(item.span, '{');
                         if let Some(snippet) = snippet_opt(cx, header_span);
                         then {
@@ -122,7 +143,7 @@ fn is_doc_hidden(attr: &Attribute) -> bool {
 
 fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) {
     fn is_private(field: &StructField) -> bool {
-        matches!(field.vis.node, VisibilityKind::Inherited)
+        matches!(field.vis.kind, VisibilityKind::Inherited)
     }
 
     fn is_non_exhaustive_marker(field: &StructField) -> bool {
@@ -141,7 +162,7 @@ fn find_header_span(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) -> S
 
     let fields = data.fields();
     let private_fields = fields.iter().filter(|f| is_private(f)).count();
-    let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count();
+    let public_fields = fields.iter().filter(|f| f.vis.kind.is_pub()).count();
 
     if_chain! {
         if private_fields == 1 && public_fields >= 1 && public_fields == fields.len() - 1;
@@ -154,7 +175,7 @@ fn find_header_span(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) -> S
                 "this seems like a manual implementation of the non-exhaustive pattern",
                 |diag| {
                     if_chain! {
-                        if !attr::contains_name(&item.attrs, sym!(non_exhaustive));
+                        if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive));
                         let header_span = find_header_span(cx, item, data);
                         if let Some(snippet) = snippet_opt(cx, header_span);
                         then {