about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tests/ui/single_match.fixed209
-rw-r--r--tests/ui/single_match.rs4
-rw-r--r--tests/ui/single_match_else.fixed173
-rw-r--r--tests/ui/single_match_else.rs2
4 files changed, 385 insertions, 3 deletions
diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed
new file mode 100644
index 00000000000..77a2cf3b991
--- /dev/null
+++ b/tests/ui/single_match.fixed
@@ -0,0 +1,209 @@
+//@run-rustfix
+#![warn(clippy::single_match)]
+#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
+fn dummy() {}
+
+fn single_match() {
+    let x = Some(1u8);
+
+    if let Some(y) = x {
+        println!("{:?}", y);
+    };
+
+    let x = Some(1u8);
+    if let Some(y) = x { println!("{:?}", y) }
+
+    let z = (1u8, 1u8);
+    if let (2..=3, 7..=9) = z { dummy() };
+
+    // Not linted (pattern guards used)
+    match x {
+        Some(y) if y == 0 => println!("{:?}", y),
+        _ => (),
+    }
+
+    // Not linted (no block with statements in the single arm)
+    match z {
+        (2..=3, 7..=9) => println!("{:?}", z),
+        _ => println!("nope"),
+    }
+}
+
+enum Foo {
+    Bar,
+    Baz(u8),
+}
+use std::borrow::Cow;
+use Foo::*;
+
+fn single_match_know_enum() {
+    let x = Some(1u8);
+    let y: Result<_, i8> = Ok(1i8);
+
+    if let Some(y) = x { dummy() };
+
+    if let Ok(y) = y { dummy() };
+
+    let c = Cow::Borrowed("");
+
+    if let Cow::Borrowed(..) = c { dummy() };
+
+    let z = Foo::Bar;
+    // no warning
+    match z {
+        Bar => println!("42"),
+        Baz(_) => (),
+    }
+
+    match z {
+        Baz(_) => println!("42"),
+        Bar => (),
+    }
+}
+
+// issue #173
+fn if_suggestion() {
+    let x = "test";
+    if x == "test" { println!() }
+
+    #[derive(PartialEq, Eq)]
+    enum Foo {
+        A,
+        B,
+        C(u32),
+    }
+
+    let x = Foo::A;
+    if x == Foo::A { println!() }
+
+    const FOO_C: Foo = Foo::C(0);
+    if x == FOO_C { println!() }
+
+    if x == Foo::A { println!() }
+
+    let x = &x;
+    if x == &Foo::A { println!() }
+
+    enum Bar {
+        A,
+        B,
+    }
+    impl PartialEq for Bar {
+        fn eq(&self, rhs: &Self) -> bool {
+            matches!((self, rhs), (Self::A, Self::A) | (Self::B, Self::B))
+        }
+    }
+    impl Eq for Bar {}
+
+    let x = Bar::A;
+    if let Bar::A = x { println!() }
+
+    // issue #7038
+    struct X;
+    let x = Some(X);
+    if let None = x { println!() };
+}
+
+// See: issue #8282
+fn ranges() {
+    enum E {
+        V,
+    }
+    let x = (Some(E::V), Some(42));
+
+    // Don't lint, because the `E` enum can be extended with additional fields later. Thus, the
+    // proposed replacement to `if let Some(E::V)` may hide non-exhaustive warnings that appeared
+    // because of `match` construction.
+    match x {
+        (Some(E::V), _) => {},
+        (None, _) => {},
+    }
+
+    // lint
+    if let (Some(_), _) = x {}
+
+    // lint
+    if let (Some(E::V), _) = x { todo!() }
+
+    // lint
+    if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (.., Some(E::V), _) => {},
+        (.., None, _) => {},
+    }
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (Some(E::V), ..) => {},
+        (None, ..) => {},
+    }
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (_, Some(E::V), ..) => {},
+        (_, None, ..) => {},
+    }
+}
+
+fn skip_type_aliases() {
+    enum OptionEx {
+        Some(i32),
+        None,
+    }
+    enum ResultEx {
+        Err(i32),
+        Ok(i32),
+    }
+
+    use OptionEx::{None, Some};
+    use ResultEx::{Err, Ok};
+
+    // don't lint
+    match Err(42) {
+        Ok(_) => dummy(),
+        Err(_) => (),
+    };
+
+    // don't lint
+    match Some(1i32) {
+        Some(_) => dummy(),
+        None => (),
+    };
+}
+
+macro_rules! single_match {
+    ($num:literal) => {
+        match $num {
+            15 => println!("15"),
+            _ => (),
+        }
+    };
+}
+
+fn main() {
+    single_match!(5);
+
+    // Don't lint
+    let _ = match Some(0) {
+        #[cfg(feature = "foo")]
+        Some(10) => 11,
+        Some(x) => x,
+        _ => 0,
+    };
+}
+
+fn issue_10808(bar: Option<i32>) {
+    if let Some(v) = bar { unsafe {
+        let r = &v as *const i32;
+        println!("{}", *r);
+    } }
+
+    if let Some(v) = bar {
+        unsafe {
+            let r = &v as *const i32;
+            println!("{}", *r);
+        }
+    }
+}
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index 3455ca5537a..8d0ab5b99ad 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -1,6 +1,6 @@
+//@run-rustfix
 #![warn(clippy::single_match)]
-#![allow(unused, clippy::uninlined_format_args)]
-
+#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
 fn dummy() {}
 
 fn single_match() {
diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed
new file mode 100644
index 00000000000..f88498655a4
--- /dev/null
+++ b/tests/ui/single_match_else.fixed
@@ -0,0 +1,173 @@
+//@run-rustfix
+//@aux-build: proc_macros.rs
+#![warn(clippy::single_match_else)]
+#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
+extern crate proc_macros;
+use proc_macros::with_span;
+
+enum ExprNode {
+    ExprAddrOf,
+    Butterflies,
+    Unicorns,
+}
+
+static NODE: ExprNode = ExprNode::Unicorns;
+
+fn unwrap_addr() -> Option<&'static ExprNode> {
+    let _ = if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else {
+        let x = 5;
+        None
+    };
+
+    // Don't lint
+    with_span!(span match ExprNode::Butterflies {
+        ExprNode::ExprAddrOf => Some(&NODE),
+        _ => {
+            let x = 5;
+            None
+        },
+    })
+}
+
+macro_rules! unwrap_addr {
+    ($expression:expr) => {
+        match $expression {
+            ExprNode::ExprAddrOf => Some(&NODE),
+            _ => {
+                let x = 5;
+                None
+            },
+        }
+    };
+}
+
+#[rustfmt::skip]
+fn main() {
+    unwrap_addr!(ExprNode::Unicorns);
+
+    //
+    // don't lint single exprs/statements
+    //
+
+    // don't lint here
+    match Some(1) {
+        Some(a) => println!("${:?}", a),
+        None => return,
+    }
+
+    // don't lint here
+    match Some(1) {
+        Some(a) => println!("${:?}", a),
+        None => {
+            return
+        },
+    }
+
+    // don't lint here
+    match Some(1) {
+        Some(a) => println!("${:?}", a),
+        None => {
+            return;
+        },
+    }
+
+    //
+    // lint multiple exprs/statements "else" blocks
+    //
+
+    // lint here
+    if let Some(a) = Some(1) { println!("${:?}", a) } else {
+        println!("else block");
+        return
+    }
+
+    // lint here
+    if let Some(a) = Some(1) { println!("${:?}", a) } else {
+        println!("else block");
+        return;
+    }
+
+    // lint here
+    use std::convert::Infallible;
+    if let Ok(a) = Result::<i32, Infallible>::Ok(1) { println!("${:?}", a) } else {
+        println!("else block");
+        return;
+    }
+
+    use std::borrow::Cow;
+    if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else {
+        println!("else block");
+        return;
+    }
+}
+
+fn issue_10808(bar: Option<i32>) {
+    if let Some(v) = bar { unsafe {
+        let r = &v as *const i32;
+        println!("{}", *r);
+    } } else {
+        println!("None1");
+        println!("None2");
+    }
+
+    if let Some(v) = bar {
+        println!("Some");
+        println!("{v}");
+    } else { unsafe {
+        let v = 0;
+        let r = &v as *const i32;
+        println!("{}", *r);
+    } }
+
+    if let Some(v) = bar { unsafe {
+        let r = &v as *const i32;
+        println!("{}", *r);
+    } } else { unsafe {
+        let v = 0;
+        let r = &v as *const i32;
+        println!("{}", *r);
+    } }
+
+    if let Some(v) = bar {
+        unsafe {
+            let r = &v as *const i32;
+            println!("{}", *r);
+        }
+    } else {
+        println!("None");
+        println!("None");
+    }
+
+    match bar {
+        Some(v) => {
+            println!("Some");
+            println!("{v}");
+        },
+        #[rustfmt::skip]
+        None => {
+            unsafe {
+                let v = 0;
+                let r = &v as *const i32;
+                println!("{}", *r);
+            }
+        },
+    }
+
+    match bar {
+        #[rustfmt::skip]
+        Some(v) => {
+            unsafe {
+                let r = &v as *const i32;
+                println!("{}", *r);
+            }
+        },
+        #[rustfmt::skip]
+        None => {
+            unsafe {
+                let v = 0;
+                let r = &v as *const i32;
+                println!("{}", *r);
+            }
+        },
+    }
+}
diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs
index ec97bfc845f..b34b9553919 100644
--- a/tests/ui/single_match_else.rs
+++ b/tests/ui/single_match_else.rs
@@ -1,7 +1,7 @@
+//@run-rustfix
 //@aux-build: proc_macros.rs
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
-
 extern crate proc_macros;
 use proc_macros::with_span;