about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThibsG <Thibs@debian.com>2020-01-02 20:00:27 +0100
committerThibsG <Thibs@debian.com>2020-01-07 18:48:16 +0100
commit58deaad42d2986154303647dbc005133aaf3ab92 (patch)
tree1c8a7910fed0f582c7f8d01e43f4dc6f37745ea6
parentd60c6f939862ed0be315499f53a0c2fe63b580d6 (diff)
downloadrust-58deaad42d2986154303647dbc005133aaf3ab92.tar.gz
rust-58deaad42d2986154303647dbc005133aaf3ab92.zip
Handle case for non-exhaustive enums
-rw-r--r--clippy_lints/src/matches.rs45
-rw-r--r--tests/ui/pats_with_wild_match_arm.stderr16
2 files changed, 43 insertions, 18 deletions
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index e7d9b9413f1..2347a0619d6 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -267,7 +267,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches {
             check_wild_err_arm(cx, ex, arms);
             check_wild_enum_match(cx, ex, arms);
             check_match_as_ref(cx, ex, arms, expr);
-            check_pats_wild_match(cx, arms);
+            check_pats_wild_match(cx, ex, arms);
         }
         if let ExprKind::Match(ref ex, ref arms, _) = expr.kind {
             check_match_ref_pats(cx, ex, arms, expr);
@@ -686,20 +686,45 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>],
     }
 }
 
-fn check_pats_wild_match(cx: &LateContext<'_, '_>, arms: &[Arm]) {
+fn check_pats_wild_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
+    let mut is_non_exhaustive_enum = false;
+    let ty = cx.tables.expr_ty(ex);
+    if ty.is_enum() {
+        if let ty::Adt(def, _) = ty.kind {
+            if def.is_variant_list_non_exhaustive() {
+                is_non_exhaustive_enum = true;
+            }
+        }
+    }
+
     for arm in arms {
         if let PatKind::Or(ref fields) = arm.pat.kind {
-            // look for multiple fields where one at least matches Wild pattern
-            if fields.len() > 1 && fields.into_iter().any(is_wild) {
-                span_lint_and_sugg(
+            // look for multiple fields in this arm that contains at least one Wild pattern
+            if fields.len() > 1 && fields.iter().any(is_wild) {
+                span_lint_and_then(
                     cx,
                     PATS_WITH_WILD_MATCH_ARM,
                     arm.pat.span,
-                    "wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only",
-                    "try this",
-                    "_".to_string(),
-                    Applicability::MachineApplicable,
-                )
+                    "wildcard pattern covers any other pattern as it will match anyway.",
+                    |db| {
+                        // handle case where a non exhaustive enum is being used
+                        if is_non_exhaustive_enum {
+                            db.span_suggestion(
+                                arm.pat.span,
+                                "consider handling `_` separately.",
+                                "_ => ...".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            db.span_suggestion(
+                                arm.pat.span,
+                                "consider replacing with wildcard pattern only",
+                                "_".to_string(),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    },
+                );
             }
         }
     }
diff --git a/tests/ui/pats_with_wild_match_arm.stderr b/tests/ui/pats_with_wild_match_arm.stderr
index 5b5d8d28738..215d0b2e413 100644
--- a/tests/ui/pats_with_wild_match_arm.stderr
+++ b/tests/ui/pats_with_wild_match_arm.stderr
@@ -1,28 +1,28 @@
-error: wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only
+error: wildcard pattern covers any other pattern as it will match anyway.
   --> $DIR/pats_with_wild_match_arm.rs:10:9
    |
 LL |         "bar" | _ => {
-   |         ^^^^^^^^^ help: try this: `_`
+   |         ^^^^^^^^^ help: consider replacing with wildcard pattern only: `_`
    |
    = note: `-D clippy::pats-with-wild-match-arm` implied by `-D warnings`
 
-error: wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only
+error: wildcard pattern covers any other pattern as it will match anyway.
   --> $DIR/pats_with_wild_match_arm.rs:18:9
    |
 LL |         "bar" | "bar2" | _ => {
-   |         ^^^^^^^^^^^^^^^^^^ help: try this: `_`
+   |         ^^^^^^^^^^^^^^^^^^ help: consider replacing with wildcard pattern only: `_`
 
-error: wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only
+error: wildcard pattern covers any other pattern as it will match anyway.
   --> $DIR/pats_with_wild_match_arm.rs:26:9
    |
 LL |         _ | "bar" | _ => {
-   |         ^^^^^^^^^^^^^ help: try this: `_`
+   |         ^^^^^^^^^^^^^ help: consider replacing with wildcard pattern only: `_`
 
-error: wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only
+error: wildcard pattern covers any other pattern as it will match anyway.
   --> $DIR/pats_with_wild_match_arm.rs:34:9
    |
 LL |         _ | "bar" => {
-   |         ^^^^^^^^^ help: try this: `_`
+   |         ^^^^^^^^^ help: consider replacing with wildcard pattern only: `_`
 
 error: aborting due to 4 previous errors