about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPhilipp Hansch <dev@phansch.net>2018-10-17 07:31:09 +0200
committerGitHub <noreply@github.com>2018-10-17 07:31:09 +0200
commit284c63e84d21a844c0cbe6fc9d227f381f1b5130 (patch)
tree6768af67af1073207d61b137519719e2ed093310
parentb0ab69fcf18cd7e4c7894d5cea40f2abcc9e75a2 (diff)
parent66ae3b124949d07c2a50e051b166b93029ecc4ca (diff)
downloadrust-284c63e84d21a844c0cbe6fc9d227f381f1b5130.tar.gz
rust-284c63e84d21a844c0cbe6fc9d227f381f1b5130.zip
Merge pull request #3281 from CYBAI/redundant-match
Add lint for redundant pattern matching for explicit return boolean
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/deprecated_lints.rs12
-rw-r--r--clippy_lints/src/if_let_redundant_pattern_matching.rs103
-rw-r--r--clippy_lints/src/lib.rs12
-rw-r--r--clippy_lints/src/redundant_pattern_matching.rs228
-rw-r--r--tests/ui/if_let_redundant_pattern_matching.stderr34
-rw-r--r--tests/ui/matches.rs2
-rw-r--r--tests/ui/needless_pass_by_value.rs2
-rw-r--r--tests/ui/redundant_pattern_matching.rs (renamed from tests/ui/if_let_redundant_pattern_matching.rs)32
-rw-r--r--tests/ui/redundant_pattern_matching.stderr88
10 files changed, 369 insertions, 145 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6792c06894..626c39457e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -816,6 +816,7 @@ All notable changes to this project will be documented in this file.
 [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call
 [`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names
 [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern
+[`redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern_matching
 [`ref_in_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ref_in_deref
 [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro
 [`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts
diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs
index 0067629bbd0..904036fe888 100644
--- a/clippy_lints/src/deprecated_lints.rs
+++ b/clippy_lints/src/deprecated_lints.rs
@@ -16,7 +16,7 @@ macro_rules! declare_deprecated_lint {
 
 /// **What it does:** Nothing. This lint has been deprecated.
 ///
-/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend 
+/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend
 /// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011.
 declare_deprecated_lint! {
     pub SHOULD_ASSERT_EQ,
@@ -102,3 +102,13 @@ declare_deprecated_lint! {
     pub ASSIGN_OPS,
     "using compound assignment operators (e.g. `+=`) is harmless"
 }
+
+/// **What it does:** Nothing. This lint has been deprecated.
+///
+/// **Deprecation reason:** The original rule will only lint for `if let`. After
+/// making it support to lint `match`, naming as `if let` is not suitable for it.
+/// So, this lint is deprecated.
+declare_deprecated_lint! {
+    pub IF_LET_REDUNDANT_PATTERN_MATCHING,
+    "this lint has been changed to redundant_pattern_matching"
+}
diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs
deleted file mode 100644
index bced0c9552d..00000000000
--- a/clippy_lints/src/if_let_redundant_pattern_matching.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
-use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
-use crate::rustc_errors::Applicability;
-
-/// **What it does:** Lint for redundant pattern matching over `Result` or
-/// `Option`
-///
-/// **Why is this bad?** It's more concise and clear to just use the proper
-/// utility function
-///
-/// **Known problems:** None.
-///
-/// **Example:**
-///
-/// ```rust
-/// if let Ok(_) = Ok::<i32, i32>(42) {}
-/// if let Err(_) = Err::<i32, i32>(42) {}
-/// if let None = None::<()> {}
-/// if let Some(_) = Some(42) {}
-/// ```
-///
-/// The more idiomatic use would be:
-///
-/// ```rust
-/// if Ok::<i32, i32>(42).is_ok() {}
-/// if Err::<i32, i32>(42).is_err() {}
-/// if None::<()>.is_none() {}
-/// if Some(42).is_some() {}
-/// ```
-///
-declare_clippy_lint! {
-    pub IF_LET_REDUNDANT_PATTERN_MATCHING,
-    style,
-    "use the proper utility function avoiding an `if let`"
-}
-
-#[derive(Copy, Clone)]
-pub struct Pass;
-
-impl LintPass for Pass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IF_LET_REDUNDANT_PATTERN_MATCHING)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
-    #[allow(clippy::similar_names)]
-    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
-        if let ExprKind::Match(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node {
-            if arms[0].pats.len() == 1 {
-                let good_method = match arms[0].pats[0].node {
-                    PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => {
-                        if let PatKind::Wild = pats[0].node {
-                            if match_qpath(path, &paths::RESULT_OK) {
-                                "is_ok()"
-                            } else if match_qpath(path, &paths::RESULT_ERR) {
-                                "is_err()"
-                            } else if match_qpath(path, &paths::OPTION_SOME) {
-                                "is_some()"
-                            } else {
-                                return;
-                            }
-                        } else {
-                            return;
-                        }
-                    },
-
-                    PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()",
-
-                    _ => return,
-                };
-
-                span_lint_and_then(
-                    cx,
-                    IF_LET_REDUNDANT_PATTERN_MATCHING,
-                    arms[0].pats[0].span,
-                    &format!("redundant pattern matching, consider using `{}`", good_method),
-                    |db| {
-                        let span = expr.span.to(op.span);
-                        db.span_suggestion_with_applicability(
-                            span,
-                            "try this",
-                            format!("if {}.{}", snippet(cx, op.span, "_"), good_method),
-                            Applicability::MachineApplicable, // snippet
-                        );
-                    },
-                );
-            }
-        }
-    }
-}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 35c89e4efde..23bd71a08ab 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -126,7 +126,6 @@ pub mod formatting;
 pub mod functions;
 pub mod identity_conversion;
 pub mod identity_op;
-pub mod if_let_redundant_pattern_matching;
 pub mod if_not_else;
 pub mod indexing_slicing;
 pub mod infallible_destructuring_match;
@@ -180,6 +179,7 @@ pub mod ptr_offset_with_cast;
 pub mod question_mark;
 pub mod ranges;
 pub mod redundant_field_names;
+pub mod redundant_pattern_matching;
 pub mod reference;
 pub mod regex;
 pub mod replace_consts;
@@ -303,6 +303,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         "assign_ops",
         "using compound assignment operators (e.g. `+=`) is harmless",
     );
+    store.register_removed(
+        "if_let_redundant_pattern_matching",
+        "this lint has been changed to redundant_pattern_matching",
+    );
     // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 
     reg.register_late_lint_pass(box serde_api::Serde);
@@ -402,7 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
     reg.register_late_lint_pass(box missing_doc::MissingDoc::new());
     reg.register_late_lint_pass(box missing_inline::MissingInline);
     reg.register_late_lint_pass(box ok_if_let::Pass);
-    reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
+    reg.register_late_lint_pass(box redundant_pattern_matching::Pass);
     reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
     reg.register_early_lint_pass(box reference::Pass);
     reg.register_early_lint_pass(box reference::DerefPass);
@@ -565,7 +569,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         functions::TOO_MANY_ARGUMENTS,
         identity_conversion::IDENTITY_CONVERSION,
         identity_op::IDENTITY_OP,
-        if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING,
         indexing_slicing::OUT_OF_BOUNDS_INDEXING,
         infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
         infinite_iter::INFINITE_ITER,
@@ -680,6 +683,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         ranges::RANGE_PLUS_ONE,
         ranges::RANGE_ZIP_WITH_LEN,
         redundant_field_names::REDUNDANT_FIELD_NAMES,
+        redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING,
         reference::DEREF_ADDROF,
         reference::REF_IN_DEREF,
         regex::INVALID_REGEX,
@@ -749,7 +753,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         excessive_precision::EXCESSIVE_PRECISION,
         formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
         formatting::SUSPICIOUS_ELSE_FORMATTING,
-        if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING,
         infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
         len_zero::LEN_WITHOUT_IS_EMPTY,
         len_zero::LEN_ZERO,
@@ -800,6 +803,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         ptr::PTR_ARG,
         question_mark::QUESTION_MARK,
         redundant_field_names::REDUNDANT_FIELD_NAMES,
+        redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING,
         regex::REGEX_MACRO,
         regex::TRIVIAL_REGEX,
         returns::LET_AND_RETURN,
diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs
new file mode 100644
index 00000000000..f8c5b29bad1
--- /dev/null
+++ b/clippy_lints/src/redundant_pattern_matching.rs
@@ -0,0 +1,228 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc::hir::*;
+use crate::syntax::ptr::P;
+use crate::syntax::ast::LitKind;
+use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
+use crate::rustc_errors::Applicability;
+
+/// **What it does:** Lint for redundant pattern matching over `Result` or
+/// `Option`
+///
+/// **Why is this bad?** It's more concise and clear to just use the proper
+/// utility function
+///
+/// **Known problems:** None.
+///
+/// **Example:**
+///
+/// ```rust
+/// if let Ok(_) = Ok::<i32, i32>(42) {}
+/// if let Err(_) = Err::<i32, i32>(42) {}
+/// if let None = None::<()> {}
+/// if let Some(_) = Some(42) {}
+/// match Ok::<i32, i32>(42) {
+///     Ok(_) => true,
+///     Err(_) => false,
+/// };
+/// ```
+///
+/// The more idiomatic use would be:
+///
+/// ```rust
+/// if Ok::<i32, i32>(42).is_ok() {}
+/// if Err::<i32, i32>(42).is_err() {}
+/// if None::<()>.is_none() {}
+/// if Some(42).is_some() {}
+/// Ok::<i32, i32>(42).is_ok();
+/// ```
+///
+declare_clippy_lint! {
+    pub REDUNDANT_PATTERN_MATCHING,
+    style,
+    "use the proper utility function avoiding an `if let`"
+}
+
+#[derive(Copy, Clone)]
+pub struct Pass;
+
+impl LintPass for Pass {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(REDUNDANT_PATTERN_MATCHING)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
+    #[allow(clippy::similar_names)]
+    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
+        if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node {
+            match match_source {
+                MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms),
+                MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms),
+                _ => return,
+            }
+        }
+    }
+}
+
+fn find_sugg_for_if_let<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    expr: &'tcx Expr,
+    op: &P<Expr>,
+    arms: &HirVec<Arm>
+) {
+    if arms[0].pats.len() == 1 {
+        let good_method = match arms[0].pats[0].node {
+            PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => {
+                if let PatKind::Wild = pats[0].node {
+                    if match_qpath(path, &paths::RESULT_OK) {
+                        "is_ok()"
+                    } else if match_qpath(path, &paths::RESULT_ERR) {
+                        "is_err()"
+                    } else if match_qpath(path, &paths::OPTION_SOME) {
+                        "is_some()"
+                    } else {
+                        return;
+                    }
+                } else {
+                    return;
+                }
+            },
+
+            PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()",
+
+            _ => return,
+        };
+
+        span_lint_and_then(
+            cx,
+            REDUNDANT_PATTERN_MATCHING,
+            arms[0].pats[0].span,
+            &format!("redundant pattern matching, consider using `{}`", good_method),
+            |db| {
+                let span = expr.span.to(op.span);
+                db.span_suggestion_with_applicability(
+                    span,
+                    "try this",
+                    format!("if {}.{}", snippet(cx, op.span, "_"), good_method),
+                    Applicability::MachineApplicable, // snippet
+                );
+            },
+        );
+    } else {
+        return;
+    }
+}
+
+fn find_sugg_for_match<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    expr: &'tcx Expr,
+    op: &P<Expr>,
+    arms: &HirVec<Arm>
+) {
+    if arms.len() == 2 {
+        let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node);
+
+        let found_good_method = match node_pair {
+            (
+                PatKind::TupleStruct(ref path_left, ref pats_left, _),
+                PatKind::TupleStruct(ref path_right, ref pats_right, _)
+            ) if pats_left.len() == 1 && pats_right.len() == 1 => {
+                if let (PatKind::Wild, PatKind::Wild) = (&pats_left[0].node, &pats_right[0].node) {
+                    find_good_method_for_match(
+                        arms,
+                        path_left,
+                        path_right,
+                        &paths::RESULT_OK,
+                        &paths::RESULT_ERR,
+                        "is_ok()",
+                        "is_err()"
+                    )
+                } else {
+                    None
+                }
+            },
+            (
+                PatKind::TupleStruct(ref path_left, ref pats, _),
+                PatKind::Path(ref path_right)
+            ) | (
+                PatKind::Path(ref path_left),
+                PatKind::TupleStruct(ref path_right, ref pats, _)
+            ) if pats.len() == 1 => {
+                if let PatKind::Wild = pats[0].node {
+                    find_good_method_for_match(
+                        arms,
+                        path_left,
+                        path_right,
+                        &paths::OPTION_SOME,
+                        &paths::OPTION_NONE,
+                        "is_some()",
+                        "is_none()"
+                    )
+                } else {
+                    None
+                }
+            },
+            _ => None,
+        };
+
+        if let Some(good_method) = found_good_method {
+            span_lint_and_then(
+                cx,
+                REDUNDANT_PATTERN_MATCHING,
+                expr.span,
+                &format!("redundant pattern matching, consider using `{}`", good_method),
+                |db| {
+                    let span = expr.span.to(op.span);
+                    db.span_suggestion_with_applicability(
+                        span,
+                        "try this",
+                        format!("{}.{}", snippet(cx, op.span, "_"), good_method),
+                        Applicability::MachineApplicable, // snippet
+                    );
+                },
+            );
+        }
+    } else {
+        return;
+    }
+}
+
+fn find_good_method_for_match<'a>(
+    arms: &HirVec<Arm>,
+    path_left: &QPath,
+    path_right: &QPath,
+    expected_left: &[&str],
+    expected_right: &[&str],
+    should_be_left: &'a str,
+    should_be_right: &'a str
+) -> Option<&'a str> {
+    let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) {
+        (&(*arms[0].body).node, &(*arms[1].body).node)
+    } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) {
+        (&(*arms[1].body).node, &(*arms[0].body).node)
+    } else {
+        return None;
+    };
+
+    match body_node_pair {
+        (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => {
+            match (&lit_left.node, &lit_right.node) {
+                (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+                (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+                _ => None,
+            }
+        },
+        _ => None,
+    }
+}
diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr
deleted file mode 100644
index 5111de67189..00000000000
--- a/tests/ui/if_let_redundant_pattern_matching.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/if_let_redundant_pattern_matching.rs:19:12
-   |
-19 |     if let Ok(_) = Ok::<i32, i32>(42) {}
-   |     -------^^^^^------------------------ help: try this: `if Ok::<i32, i32>(42).is_ok()`
-   |
-   = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/if_let_redundant_pattern_matching.rs:21:12
-   |
-21 |       if let Err(_) = Err::<i32, i32>(42) {
-   |  _____-      ^^^^^^
-22 | |     }
-   | |_____- help: try this: `if Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/if_let_redundant_pattern_matching.rs:24:12
-   |
-24 |       if let None = None::<()> {
-   |  _____-      ^^^^
-25 | |     }
-   | |_____- help: try this: `if None::<()>.is_none()`
-
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/if_let_redundant_pattern_matching.rs:27:12
-   |
-27 |       if let Some(_) = Some(42) {
-   |  _____-      ^^^^^^^
-28 | |     }
-   | |_____- help: try this: `if Some(42).is_some()`
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs
index c43fead08f8..d31e97c7959 100644
--- a/tests/ui/matches.rs
+++ b/tests/ui/matches.rs
@@ -13,7 +13,7 @@
 
 
 #![warn(clippy::all)]
-#![allow(unused, clippy::if_let_redundant_pattern_matching)]
+#![allow(unused, clippy::redundant_pattern_matching)]
 #![warn(clippy::single_match_else, clippy::match_same_arms)]
 
 enum ExprNode {
diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs
index 5825d9e9074..48b7b42cc8c 100644
--- a/tests/ui/needless_pass_by_value.rs
+++ b/tests/ui/needless_pass_by_value.rs
@@ -11,7 +11,7 @@
 
 
 #![warn(clippy::needless_pass_by_value)]
-#![allow(dead_code, clippy::single_match, clippy::if_let_redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)]
+#![allow(dead_code, clippy::single_match, clippy::redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)]
 
 use std::borrow::Borrow;
 use std::convert::AsRef;
diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs
index 1c0e7e79c68..50838584f66 100644
--- a/tests/ui/if_let_redundant_pattern_matching.rs
+++ b/tests/ui/redundant_pattern_matching.rs
@@ -12,7 +12,7 @@
 
 
 #![warn(clippy::all)]
-#![warn(clippy::if_let_redundant_pattern_matching)]
+#![warn(clippy::redundant_pattern_matching)]
 
 
 fn main() {
@@ -42,4 +42,34 @@ fn main() {
     if let Ok(x) = Ok::<i32,i32>(42) {
         println!("{}", x);
     }
+
+    match Ok::<i32, i32>(42) {
+        Ok(_) => true,
+        Err(_) => false,
+    };
+
+    match Ok::<i32, i32>(42) {
+        Ok(_) => false,
+        Err(_) => true,
+    };
+
+    match Err::<i32, i32>(42) {
+        Ok(_) => false,
+        Err(_) => true,
+    };
+
+    match Err::<i32, i32>(42) {
+        Ok(_) => true,
+        Err(_) => false,
+    };
+
+    match Some(42) {
+        Some(_) => true,
+        None => false,
+    };
+
+    match None::<()> {
+        Some(_) => false,
+        None => true,
+    };
 }
diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr
new file mode 100644
index 00000000000..a42ac7ba04d
--- /dev/null
+++ b/tests/ui/redundant_pattern_matching.stderr
@@ -0,0 +1,88 @@
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching.rs:19:12
+   |
+19 |     if let Ok(_) = Ok::<i32, i32>(42) {}
+   |     -------^^^^^------------------------ help: try this: `if Ok::<i32, i32>(42).is_ok()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching.rs:21:12
+   |
+21 |       if let Err(_) = Err::<i32, i32>(42) {
+   |  _____-      ^^^^^^
+22 | |     }
+   | |_____- help: try this: `if Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching.rs:24:12
+   |
+24 |       if let None = None::<()> {
+   |  _____-      ^^^^
+25 | |     }
+   | |_____- help: try this: `if None::<()>.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching.rs:27:12
+   |
+27 |       if let Some(_) = Some(42) {
+   |  _____-      ^^^^^^^
+28 | |     }
+   | |_____- help: try this: `if Some(42).is_some()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching.rs:46:5
+   |
+46 | /     match Ok::<i32, i32>(42) {
+47 | |         Ok(_) => true,
+48 | |         Err(_) => false,
+49 | |     };
+   | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching.rs:51:5
+   |
+51 | /     match Ok::<i32, i32>(42) {
+52 | |         Ok(_) => false,
+53 | |         Err(_) => true,
+54 | |     };
+   | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching.rs:56:5
+   |
+56 | /     match Err::<i32, i32>(42) {
+57 | |         Ok(_) => false,
+58 | |         Err(_) => true,
+59 | |     };
+   | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching.rs:61:5
+   |
+61 | /     match Err::<i32, i32>(42) {
+62 | |         Ok(_) => true,
+63 | |         Err(_) => false,
+64 | |     };
+   | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching.rs:66:5
+   |
+66 | /     match Some(42) {
+67 | |         Some(_) => true,
+68 | |         None => false,
+69 | |     };
+   | |_____^ help: try this: `Some(42).is_some()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching.rs:71:5
+   |
+71 | /     match None::<()> {
+72 | |         Some(_) => false,
+73 | |         None => true,
+74 | |     };
+   | |_____^ help: try this: `None::<()>.is_none()`
+
+error: aborting due to 10 previous errors
+