about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/matches/mod.rs2
-rw-r--r--clippy_lints/src/matches/wild_in_or_pats.rs14
-rw-r--r--tests/ui/wild_in_or_pats.rs68
-rw-r--r--tests/ui/wild_in_or_pats.stderr18
4 files changed, 97 insertions, 5 deletions
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index 686fc4a0fa0..28adcc2f227 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -1045,7 +1045,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
             if !from_expansion {
                 // These don't depend on a relationship between multiple arms
                 match_wild_err_arm::check(cx, ex, arms);
-                wild_in_or_pats::check(cx, arms);
+                wild_in_or_pats::check(cx, ex, arms);
             }
 
             if let MatchSource::TryDesugar(_) = source {
diff --git a/clippy_lints/src/matches/wild_in_or_pats.rs b/clippy_lints/src/matches/wild_in_or_pats.rs
index 459513e65bf..390ba889fd2 100644
--- a/clippy_lints/src/matches/wild_in_or_pats.rs
+++ b/clippy_lints/src/matches/wild_in_or_pats.rs
@@ -1,11 +1,19 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::is_wild;
-use rustc_hir::{Arm, PatKind};
+use clippy_utils::{has_non_exhaustive_attr, is_wild};
+use rustc_hir::{Arm, Expr, PatKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty;
 
 use super::WILDCARD_IN_OR_PATTERNS;
 
-pub(crate) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
+pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arms: &[Arm<'_>]) {
+    // first check if we are matching on an enum that has the non_exhaustive attribute
+    let ty = cx.typeck_results().expr_ty(expr).peel_refs();
+    if let ty::Adt(adt_def, _) = ty.kind()
+        && has_non_exhaustive_attr(cx.tcx, *adt_def)
+    {
+        return;
+    };
     for arm in arms {
         if let PatKind::Or(fields) = arm.pat.kind {
             // look for multiple fields in this arm that contains at least one Wild pattern
diff --git a/tests/ui/wild_in_or_pats.rs b/tests/ui/wild_in_or_pats.rs
index f8bb31b83c4..bc8a1dbee71 100644
--- a/tests/ui/wild_in_or_pats.rs
+++ b/tests/ui/wild_in_or_pats.rs
@@ -37,4 +37,72 @@ fn main() {
             dbg!("matched (bar or) wild");
         },
     };
+
+    // shouldn't lint
+    #[non_exhaustive]
+    pub enum NonExhaustiveEnum<'a> {
+        Message(&'a str),
+        Quit(&'a str),
+        Other,
+    }
+
+    match NonExhaustiveEnum::Message("Pass") {
+        NonExhaustiveEnum::Message(_) => dbg!("message"),
+        NonExhaustiveEnum::Quit(_) => dbg!("quit"),
+        NonExhaustiveEnum::Other | _ => dbg!("wildcard"),
+    };
+
+    // should lint
+    enum ExhaustiveEnum {
+        Quit,
+        Write(String),
+        ChangeColor(i32, i32, i32),
+    }
+
+    match ExhaustiveEnum::ChangeColor(0, 160, 255) {
+        ExhaustiveEnum::Write(text) => {
+            dbg!("Write");
+        },
+        ExhaustiveEnum::ChangeColor(r, g, b) => {
+            dbg!("Change the color");
+        },
+        ExhaustiveEnum::Quit | _ => {
+            dbg!("Quit or other");
+        },
+    };
+
+    // shouldn't lint
+    #[non_exhaustive]
+    struct NonExhaustiveStruct {
+        a: u32,
+        b: u32,
+        c: u64,
+    }
+
+    let b = NonExhaustiveStruct { a: 5, b: 42, c: 342 };
+
+    match b {
+        NonExhaustiveStruct { a: 5, b: 42, .. } => {},
+        NonExhaustiveStruct { a: 0, b: 0, c: 128 } => {},
+        NonExhaustiveStruct { a: 0, b: 0, c: 128, .. } | _ => {},
+    }
+
+    // should lint
+    struct ExhaustiveStruct {
+        x: i32,
+        y: i32,
+    }
+
+    let p = ExhaustiveStruct { x: 0, y: 7 };
+    match p {
+        ExhaustiveStruct { x: 0, y: 0 } => {
+            dbg!("On the x axis at {x}");
+        },
+        ExhaustiveStruct { x: 0, y: 1 } => {
+            dbg!("On the y axis at {y}");
+        },
+        ExhaustiveStruct { x: 1, y: 1 } | _ => {
+            dbg!("On neither axis: ({x}, {y})");
+        },
+    }
 }
diff --git a/tests/ui/wild_in_or_pats.stderr b/tests/ui/wild_in_or_pats.stderr
index 06b2415d221..5e409d6dfa6 100644
--- a/tests/ui/wild_in_or_pats.stderr
+++ b/tests/ui/wild_in_or_pats.stderr
@@ -32,5 +32,21 @@ LL |         _ | "bar" => {
    |
    = help: consider handling `_` separately
 
-error: aborting due to 4 previous errors
+error: wildcard pattern covers any other pattern as it will match anyway
+  --> tests/ui/wild_in_or_pats.rs:69:9
+   |
+LL |         ExhaustiveEnum::Quit | _ => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider handling `_` separately
+
+error: wildcard pattern covers any other pattern as it will match anyway
+  --> tests/ui/wild_in_or_pats.rs:104:9
+   |
+LL |         ExhaustiveStruct { x: 1, y: 1 } | _ => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider handling `_` separately
+
+error: aborting due to 6 previous errors