]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/matches.rs
match_wildcard_for_single_variants: remove empty line at start of lint example.
[rust.git] / clippy_lints / src / matches.rs
index 6fdb4cf9cd74733b51efa6ae71330cd20bcbb0d3..6d7af45a47224d54a99e6949c50185e792acf9bc 100644 (file)
     /// ```rust
     /// # fn bar(stool: &str) {}
     /// # let x = Some("abc");
+    ///
+    /// // Bad
     /// match x {
     ///     Some(ref foo) => bar(foo),
     ///     _ => (),
     /// }
+    ///
+    /// // Good
+    /// if let Some(ref foo) = x {
+    ///     bar(foo);
+    /// }
     /// ```
     pub SINGLE_MATCH,
     style,
     ///
     /// **Example:**
     /// ```rust,ignore
+    /// // Bad
     /// match x {
     ///     &A(ref y) => foo(y),
     ///     &B => bar(),
     ///     _ => frob(&x),
     /// }
+    ///
+    /// // Good
+    /// match *x {
+    ///     A(ref y) => foo(y),
+    ///     B => bar(),
+    ///     _ => frob(x),
+    /// }
     /// ```
     pub MATCH_REF_PATS,
     style,
     /// **What it does:** Checks for arm which matches all errors with `Err(_)`
     /// and take drastic actions like `panic!`.
     ///
-    /// **Why is this bad?** It is generally a bad practice, just like
+    /// **Why is this bad?** It is generally a bad practice, similar to
     /// catching all exceptions in java with `catch(Exception)`
     ///
     /// **Known problems:** None.
     /// }
     /// ```
     pub MATCH_WILD_ERR_ARM,
-    style,
+    pedantic,
     "a `match` with `Err(_)` arm and take drastic actions"
 }
 
     /// **Example:**
     /// ```rust
     /// let x: Option<()> = None;
+    ///
+    /// // Bad
     /// let r: Option<&()> = match x {
     ///     None => None,
     ///     Some(ref v) => Some(v),
     /// };
+    ///
+    /// // Good
+    /// let r: Option<&()> = x.as_ref();
     /// ```
     pub MATCH_AS_REF,
     complexity,
     /// ```rust
     /// # enum Foo { A(usize), B(usize) }
     /// # let x = Foo::B(1);
+    ///
+    /// // Bad
     /// match x {
     ///     Foo::A(_) => {},
     ///     _ => {},
     /// }
+    ///
+    /// // Good
+    /// match x {
+    ///     Foo::A(_) => {},
+    ///     Foo::B(_) => {},
+    /// }
     /// ```
     pub WILDCARD_ENUM_MATCH_ARM,
     restriction,
     /// ```rust
     /// # enum Foo { A, B, C }
     /// # let x = Foo::B;
+    /// // Bad
     /// match x {
     ///     Foo::A => {},
     ///     Foo::B => {},
     ///     _ => {},
     /// }
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// # enum Foo { A, B, C }
-    /// # let x = Foo::B;
+    ///
+    /// // Good
     /// match x {
     ///     Foo::A => {},
     ///     Foo::B => {},
     ///
     /// **Example:**
     /// ```rust
+    /// // Bad
     /// match "foo" {
     ///     "a" => {},
     ///     "bar" | _ => {},
     /// }
+    ///
+    /// // Good
+    /// match "foo" {
+    ///     "a" => {},
+    ///     _ => {},
+    /// }
     /// ```
     pub WILDCARD_IN_OR_PATTERNS,
     complexity,
@@ -711,7 +744,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                                 arm.pat.span,
                                 &format!("`Err({})` matches all errors", &ident_bind_name),
                                 None,
-                                "match each error separately or use the error output",
+                                "match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable",
                             );
                         }
                     }
@@ -764,9 +797,21 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
                 if let QPath::Resolved(_, p) = path {
                     missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
                 }
-            } else if let PatKind::TupleStruct(ref path, ..) = arm.pat.kind {
+            } else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind {
                 if let QPath::Resolved(_, p) = path {
-                    missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
+                    // Some simple checks for exhaustive patterns.
+                    // There is a room for improvements to detect more cases,
+                    // but it can be more expensive to do so.
+                    let is_pattern_exhaustive = |pat: &&Pat<'_>| {
+                        if let PatKind::Wild | PatKind::Binding(.., None) = pat.kind {
+                            true
+                        } else {
+                            false
+                        }
+                    };
+                    if patterns.iter().all(is_pattern_exhaustive) {
+                        missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
+                    }
                 }
             }
         }
@@ -868,7 +913,7 @@ fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>
 
         span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |diag| {
             if !expr.span.from_expansion() {
-                multispan_sugg(diag, msg.to_owned(), suggs);
+                multispan_sugg(diag, msg, suggs);
             }
         });
     }