about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/matches/single_match.rs21
-rw-r--r--tests/ui/single_match_else_deref_patterns.fixed53
-rw-r--r--tests/ui/single_match_else_deref_patterns.rs94
-rw-r--r--tests/ui/single_match_else_deref_patterns.stderr188
4 files changed, 348 insertions, 8 deletions
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 08c0caa4266..7e530e98ac4 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -152,21 +152,26 @@ fn report_single_pattern(
             }) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1,
             _ => pat_ref_count,
         };
-        // References are only implicitly added to the pattern, so no overflow here.
-        // e.g. will work: match &Some(_) { Some(_) => () }
-        // will not: match Some(_) { &Some(_) => () }
-        let ref_count_diff = ty_ref_count - pat_ref_count;
 
-        // Try to remove address of expressions first.
-        let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
-        let ref_count_diff = ref_count_diff - removed;
+        // References are implicitly removed when `deref_patterns` are used.
+        // They are implicitly added when match ergonomics are used.
+        let (ex, ref_or_deref_adjust) = if ty_ref_count > pat_ref_count {
+            let ref_count_diff = ty_ref_count - pat_ref_count;
+
+            // Try to remove address of expressions first.
+            let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
+
+            (ex, String::from(if ref_count_diff == removed { "" } else { "&" }))
+        } else {
+            (ex, "*".repeat(pat_ref_count - ty_ref_count))
+        };
 
         let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`";
         let sugg = format!(
             "if {} == {}{} {}{els_str}",
             snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0,
             // PartialEq for different reference counts may not exist.
-            "&".repeat(ref_count_diff),
+            ref_or_deref_adjust,
             snippet_with_applicability(cx, arm.pat.span, "..", &mut app),
             expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
         );
diff --git a/tests/ui/single_match_else_deref_patterns.fixed b/tests/ui/single_match_else_deref_patterns.fixed
new file mode 100644
index 00000000000..7a9f8063096
--- /dev/null
+++ b/tests/ui/single_match_else_deref_patterns.fixed
@@ -0,0 +1,53 @@
+#![feature(deref_patterns)]
+#![allow(
+    incomplete_features,
+    clippy::eq_op,
+    clippy::op_ref,
+    clippy::deref_addrof,
+    clippy::borrow_deref_ref,
+    clippy::needless_if
+)]
+#![deny(clippy::single_match_else)]
+
+fn string() {
+    if *"" == *"" {}
+
+    if *&*&*&*"" == *"" {}
+
+    if ***&&"" == *"" {}
+
+    if *&*&*"" == *"" {}
+
+    if **&&*"" == *"" {}
+}
+
+fn int() {
+    if &&&1 == &&&2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if &&1 == &&2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if &&1 == &&2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if &1 == &2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if &1 == &2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if 1 == 2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+    if 1 == 2 { unreachable!() } else {
+        // ok
+    }
+    //~^^^^^^ single_match_else
+}
diff --git a/tests/ui/single_match_else_deref_patterns.rs b/tests/ui/single_match_else_deref_patterns.rs
new file mode 100644
index 00000000000..ef19c7cbde2
--- /dev/null
+++ b/tests/ui/single_match_else_deref_patterns.rs
@@ -0,0 +1,94 @@
+#![feature(deref_patterns)]
+#![allow(
+    incomplete_features,
+    clippy::eq_op,
+    clippy::op_ref,
+    clippy::deref_addrof,
+    clippy::borrow_deref_ref,
+    clippy::needless_if
+)]
+#![deny(clippy::single_match_else)]
+
+fn string() {
+    match *"" {
+        //~^ single_match
+        "" => {},
+        _ => {},
+    }
+
+    match *&*&*&*"" {
+        //~^ single_match
+        "" => {},
+        _ => {},
+    }
+
+    match ***&&"" {
+        //~^ single_match
+        "" => {},
+        _ => {},
+    }
+
+    match *&*&*"" {
+        //~^ single_match
+        "" => {},
+        _ => {},
+    }
+
+    match **&&*"" {
+        //~^ single_match
+        "" => {},
+        _ => {},
+    }
+}
+
+fn int() {
+    match &&&1 {
+        &&&2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&&1 {
+        &&2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&1 {
+        &&2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&&1 {
+        &2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&1 {
+        &2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&&1 {
+        2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+    match &&1 {
+        2 => unreachable!(),
+        _ => {
+            // ok
+        },
+    }
+    //~^^^^^^ single_match_else
+}
diff --git a/tests/ui/single_match_else_deref_patterns.stderr b/tests/ui/single_match_else_deref_patterns.stderr
new file mode 100644
index 00000000000..a47df55459b
--- /dev/null
+++ b/tests/ui/single_match_else_deref_patterns.stderr
@@ -0,0 +1,188 @@
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:13:5
+   |
+LL | /     match *"" {
+LL | |
+LL | |         "" => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `if *"" == *"" {}`
+   |
+   = note: you might want to preserve the comments from inside the `match`
+   = note: `-D clippy::single-match` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::single_match)]`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:19:5
+   |
+LL | /     match *&*&*&*"" {
+LL | |
+LL | |         "" => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `if *&*&*&*"" == *"" {}`
+   |
+   = note: you might want to preserve the comments from inside the `match`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:25:5
+   |
+LL | /     match ***&&"" {
+LL | |
+LL | |         "" => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `if ***&&"" == *"" {}`
+   |
+   = note: you might want to preserve the comments from inside the `match`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:31:5
+   |
+LL | /     match *&*&*"" {
+LL | |
+LL | |         "" => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `if *&*&*"" == *"" {}`
+   |
+   = note: you might want to preserve the comments from inside the `match`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:37:5
+   |
+LL | /     match **&&*"" {
+LL | |
+LL | |         "" => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `if **&&*"" == *"" {}`
+   |
+   = note: you might want to preserve the comments from inside the `match`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:45:5
+   |
+LL | /     match &&&1 {
+LL | |         &&&2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+note: the lint level is defined here
+  --> tests/ui/single_match_else_deref_patterns.rs:10:9
+   |
+LL | #![deny(clippy::single_match_else)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try
+   |
+LL ~     if &&&1 == &&&2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:52:5
+   |
+LL | /     match &&&1 {
+LL | |         &&2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if &&1 == &&2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:59:5
+   |
+LL | /     match &&1 {
+LL | |         &&2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if &&1 == &&2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:66:5
+   |
+LL | /     match &&&1 {
+LL | |         &2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if &1 == &2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:73:5
+   |
+LL | /     match &&1 {
+LL | |         &2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if &1 == &2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:80:5
+   |
+LL | /     match &&&1 {
+LL | |         2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if 1 == 2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match_else_deref_patterns.rs:87:5
+   |
+LL | /     match &&1 {
+LL | |         2 => unreachable!(),
+LL | |         _ => {
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if 1 == 2 { unreachable!() } else {
+LL +         // ok
+LL +     }
+   |
+
+error: aborting due to 12 previous errors
+