about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Wright <mikerite@lavabit.com>2021-03-27 08:50:19 +0200
committerMichael Wright <mikerite@lavabit.com>2021-03-31 07:36:09 +0200
commit8abab5561caf0243799fba29a53e175948977ec2 (patch)
tree7060d636c3e382ea1d948086612c522824ce13cc
parent0b7671963812abc7093e56e3b5c115faf9ac701a (diff)
downloadrust-8abab5561caf0243799fba29a53e175948977ec2.tar.gz
rust-8abab5561caf0243799fba29a53e175948977ec2.zip
Fix hidden variant suggestion on single variant
Fixes #6984
-rw-r--r--clippy_lints/src/lib.rs1
-rw-r--r--clippy_lints/src/manual_non_exhaustive.rs14
-rw-r--r--clippy_lints/src/matches.rs7
-rw-r--r--clippy_lints/src/missing_doc.rs11
-rw-r--r--clippy_utils/src/attrs.rs12
-rw-r--r--tests/ui/match_wildcard_for_single_variants.fixed16
-rw-r--r--tests/ui/match_wildcard_for_single_variants.rs16
7 files changed, 54 insertions, 23 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 153972671fd..c060429edea 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -21,7 +21,6 @@
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
-extern crate rustc_attr;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 95261580b8e..7f7aeaf2be8 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,9 +1,9 @@
+use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::meets_msrv;
 use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
-use rustc_ast::ast::{Attribute, FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
-use rustc_attr as attr;
+use rustc_ast::ast::{FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_semver::RustcVersion;
@@ -102,15 +102,7 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants
     fn is_non_exhaustive_marker(variant: &Variant) -> bool {
         matches!(variant.data, VariantData::Unit(_))
             && variant.ident.as_str().starts_with('_')
-            && variant.attrs.iter().any(|a| is_doc_hidden(a))
-    }
-
-    fn is_doc_hidden(attr: &Attribute) -> bool {
-        attr.has_name(sym::doc)
-            && match attr.meta_item_list() {
-                Some(l) => attr::list_contains_name(&l, sym::hidden),
-                None => false,
-            }
+            && is_doc_hidden(&variant.attrs)
     }
 
     if_chain! {
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 425124b78f4..052bbb48887 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -983,6 +983,11 @@ impl CommonPrefixSearcher<'a> {
     }
 }
 
+fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
+    let attrs = cx.tcx.get_attrs(variant_def.def_id);
+    clippy_utils::attrs::is_doc_hidden(attrs)
+}
+
 #[allow(clippy::too_many_lines)]
 fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
     let ty = cx.typeck_results().expr_ty(ex).peel_refs();
@@ -1102,7 +1107,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 
     match missing_variants.as_slice() {
         [] => (),
-        [x] if !adt_def.is_variant_list_non_exhaustive() => span_lint_and_sugg(
+        [x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg(
             cx,
             MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
             wildcard_span,
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index ff87828c2e7..d731a9fe223 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -5,10 +5,10 @@
 // [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
 //
 
+use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
-use rustc_ast::attr;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
@@ -111,14 +111,7 @@ impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
-        let doc_hidden = self.doc_hidden()
-            || attrs.iter().any(|attr| {
-                attr.has_name(sym::doc)
-                    && match attr.meta_item_list() {
-                        None => false,
-                        Some(l) => attr::list_contains_name(&l[..], sym::hidden),
-                    }
-            });
+        let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
         self.doc_hidden_stack.push(doc_hidden);
     }
 
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index 8d28421d70d..7ec8452bf4c 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast::{ast, attr};
 use rustc_errors::Applicability;
 use rustc_session::Session;
 use rustc_span::sym;
@@ -148,3 +148,13 @@ pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'s
 pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
     attrs.iter().any(|attr| sess.is_proc_macro_attr(attr))
 }
+
+/// Return true if the attributes contain `#[doc(hidden)]`
+pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
+    #[allow(clippy::filter_map)]
+    attrs
+        .iter()
+        .filter(|attr| attr.has_name(sym::doc))
+        .flat_map(ast::Attribute::meta_item_list)
+        .any(|l| attr::list_contains_name(&l, sym::hidden))
+}
diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed
index d99f9af3faf..31b743f7a18 100644
--- a/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/tests/ui/match_wildcard_for_single_variants.fixed
@@ -108,4 +108,20 @@ fn main() {
         Bar::B => (),
         _ => (),
     };
+
+    //#6984
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            _ => (),
+        }
+    }
 }
diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs
index 1752a95de4b..d19e6ab7eb2 100644
--- a/tests/ui/match_wildcard_for_single_variants.rs
+++ b/tests/ui/match_wildcard_for_single_variants.rs
@@ -108,4 +108,20 @@ fn main() {
         Bar::B => (),
         _ => (),
     };
+
+    //#6984
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            _ => (),
+        }
+    }
 }