about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/matches.rs10
-rw-r--r--tests/ui/match_expr_like_matches_macro.fixed47
-rw-r--r--tests/ui/match_expr_like_matches_macro.rs62
-rw-r--r--tests/ui/match_expr_like_matches_macro.stderr85
4 files changed, 202 insertions, 2 deletions
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 04b35835c6b..6372cb86616 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -1185,6 +1185,14 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
             } else {
                 pat
             };
+
+            // strip potential borrows (#6503), but only if the type is a reference
+            let mut ex_new = ex;
+            if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind {
+                if let ty::Ref(..) = cx.typeck_results().expr_ty(&ex_inner).kind() {
+                    ex_new = ex_inner;
+                }
+            };
             span_lint_and_sugg(
                 cx,
                 MATCH_LIKE_MATCHES_MACRO,
@@ -1194,7 +1202,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
                 format!(
                     "{}matches!({}, {})",
                     if b0 { "" } else { "!" },
-                    snippet_with_applicability(cx, ex.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
                     pat_and_guard,
                 ),
                 applicability,
diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed
index 84981a52597..319299862a7 100644
--- a/tests/ui/match_expr_like_matches_macro.fixed
+++ b/tests/ui/match_expr_like_matches_macro.fixed
@@ -99,4 +99,51 @@ fn main() {
             _ => false,
         };
     }
+
+    {
+        // should print "z" in suggestion (#6503)
+        let z = &Some(3);
+        let _z = matches!(z, Some(3));
+    }
+
+    {
+        // this could also print "z" in suggestion..?
+        let z = Some(3);
+        let _z = matches!(&z, Some(3));
+    }
+
+    {
+        enum AnEnum {
+            X,
+            Y,
+        }
+
+        fn foo(_x: AnEnum) {}
+
+        fn main() {
+            let z = AnEnum::X;
+            // we can't remove the reference here!
+            let _ = matches!(&z, AnEnum::X);
+            foo(z);
+        }
+    }
+
+    {
+        struct S(i32);
+
+        fn fun(_val: Option<S>) {}
+        let val = Some(S(42));
+        // we need the reference here because later val is consumed by fun()
+        let _res = matches!(&val, &Some(ref _a));
+        fun(val);
+    }
+
+    {
+        struct S(i32);
+
+        fn fun(_val: Option<S>) {}
+        let val = Some(S(42));
+        let _res = matches!(&val, &Some(ref _a));
+        fun(val);
+    }
 }
diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs
index 94c7c3cadac..2ef6cf42387 100644
--- a/tests/ui/match_expr_like_matches_macro.rs
+++ b/tests/ui/match_expr_like_matches_macro.rs
@@ -119,4 +119,66 @@ fn main() {
             _ => false,
         };
     }
+
+    {
+        // should print "z" in suggestion (#6503)
+        let z = &Some(3);
+        let _z = match &z {
+            Some(3) => true,
+            _ => false,
+        };
+    }
+
+    {
+        // this could also print "z" in suggestion..?
+        let z = Some(3);
+        let _z = match &z {
+            Some(3) => true,
+            _ => false,
+        };
+    }
+
+    {
+        enum AnEnum {
+            X,
+            Y,
+        }
+
+        fn foo(_x: AnEnum) {}
+
+        fn main() {
+            let z = AnEnum::X;
+            // we can't remove the reference here!
+            let _ = match &z {
+                AnEnum::X => true,
+                _ => false,
+            };
+            foo(z);
+        }
+    }
+
+    {
+        struct S(i32);
+
+        fn fun(_val: Option<S>) {}
+        let val = Some(S(42));
+        // we need the reference here because later val is consumed by fun()
+        let _res = match &val {
+            &Some(ref _a) => true,
+            _ => false,
+        };
+        fun(val);
+    }
+
+    {
+        struct S(i32);
+
+        fn fun(_val: Option<S>) {}
+        let val = Some(S(42));
+        let _res = match &val {
+            &Some(ref _a) => true,
+            _ => false,
+        };
+        fun(val);
+    }
 }
diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr
index c52e41c7889..f27b4e9cb20 100644
--- a/tests/ui/match_expr_like_matches_macro.stderr
+++ b/tests/ui/match_expr_like_matches_macro.stderr
@@ -70,5 +70,88 @@ LL | |             _ => true,
 LL | |         };
    | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
 
-error: aborting due to 7 previous errors
+error: match expression looks like `matches!` macro
+  --> $DIR/match_expr_like_matches_macro.rs:126:18
+   |
+LL |           let _z = match &z {
+   |  __________________^
+LL | |             Some(3) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^ help: try this: `matches!(z, Some(3))`
+
+error: match expression looks like `matches!` macro
+  --> $DIR/match_expr_like_matches_macro.rs:135:18
+   |
+LL |           let _z = match &z {
+   |  __________________^
+LL | |             Some(3) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^ help: try this: `matches!(&z, Some(3))`
+
+error: match expression looks like `matches!` macro
+  --> $DIR/match_expr_like_matches_macro.rs:152:21
+   |
+LL |               let _ = match &z {
+   |  _____________________^
+LL | |                 AnEnum::X => true,
+LL | |                 _ => false,
+LL | |             };
+   | |_____________^ help: try this: `matches!(&z, AnEnum::X)`
+
+error: match expression looks like `matches!` macro
+  --> $DIR/match_expr_like_matches_macro.rs:166:20
+   |
+LL |           let _res = match &val {
+   |  ____________________^
+LL | |             &Some(ref _a) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
+
+error: you don't need to add `&` to both the expression and the patterns
+  --> $DIR/match_expr_like_matches_macro.rs:166:20
+   |
+LL |           let _res = match &val {
+   |  ____________________^
+LL | |             &Some(ref _a) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^
+   |
+   = note: `-D clippy::match-ref-pats` implied by `-D warnings`
+help: try
+   |
+LL |         let _res = match val {
+LL |             Some(ref _a) => true,
+   |
+
+error: match expression looks like `matches!` macro
+  --> $DIR/match_expr_like_matches_macro.rs:178:20
+   |
+LL |           let _res = match &val {
+   |  ____________________^
+LL | |             &Some(ref _a) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
+
+error: you don't need to add `&` to both the expression and the patterns
+  --> $DIR/match_expr_like_matches_macro.rs:178:20
+   |
+LL |           let _res = match &val {
+   |  ____________________^
+LL | |             &Some(ref _a) => true,
+LL | |             _ => false,
+LL | |         };
+   | |_________^
+   |
+help: try
+   |
+LL |         let _res = match val {
+LL |             Some(ref _a) => true,
+   |
+
+error: aborting due to 14 previous errors