about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Hamilton <alex.hamilton@ou.edu>2019-01-10 14:56:28 -0600
committerAlex Hamilton <alex.hamilton@ou.edu>2019-01-29 15:33:04 -0600
commit0da18677f733f392ef7fa8d833ade3b66bf83f9a (patch)
tree8edf2d214536ce4caca1d03177adae758d0ea534
parent6b1a2a9c3e1c8443d30247aa0d02f64d9f44e107 (diff)
downloadrust-0da18677f733f392ef7fa8d833ade3b66bf83f9a.tar.gz
rust-0da18677f733f392ef7fa8d833ade3b66bf83f9a.zip
Add match_wild lint (#3649).
This lint prevents using a wildcard in a match.
-rw-r--r--clippy_lints/src/matches.rs39
1 files changed, 38 insertions, 1 deletions
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index b290980fc36..4be045175bb 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -187,6 +187,25 @@ declare_clippy_lint! {
     "a match on an Option value instead of using `as_ref()` or `as_mut`"
 }
 
+/// **What it does:** Checks for wildcard matches using `_`.
+///
+/// **Why is this bad?** New variants added by library updates can be missed.
+///
+/// **Known problems:** None.
+///
+/// **Example:**
+/// ```rust
+/// match x {
+///     A => {},
+///     _ => {}
+/// }
+/// ```
+declare_clippy_lint! {
+    pub MATCH_WILD,
+    restriction,
+    "a wildcard match arm using `_`"
+}
+
 #[allow(missing_copy_implementations)]
 pub struct MatchPass;
 
@@ -199,7 +218,8 @@ impl LintPass for MatchPass {
             SINGLE_MATCH_ELSE,
             MATCH_OVERLAPPING_ARM,
             MATCH_WILD_ERR_ARM,
-            MATCH_AS_REF
+            MATCH_AS_REF,
+            MATCH_WILD
         )
     }
 
@@ -218,6 +238,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass {
             check_match_bool(cx, ex, arms, expr);
             check_overlapping_arms(cx, ex, arms);
             check_wild_err_arm(cx, ex, arms);
+            check_wild_arm(cx, ex, arms);
             check_match_as_ref(cx, ex, arms, expr);
         }
         if let ExprKind::Match(ref ex, ref arms, _) = expr.node {
@@ -442,6 +463,22 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
     }
 }
 
+fn check_wild_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
+    let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
+    if match_type(cx, ex_ty, &paths::RESULT) {
+        for arm in arms {
+            if is_wild(&arm.pats[0]) {
+                span_note_and_lint(cx,
+                    MATCH_WILD,
+                    arm.pats[0].span,
+                    "Wildcard match will miss any future added variants.",
+                    arm.pats[0].span,
+                    "to resolve, match each variant explicitly");
+            }
+        }
+    }
+}
+
 // If the block contains only a `panic!` macro (as expression or statement)
 fn is_panic_block(block: &Block) -> bool {
     match (&block.expr, block.stmts.len(), block.stmts.first()) {