]> git.lizzy.rs Git - rust.git/blobdiff - tests/ui/manual_unwrap_or.rs
fix invalid code suggestion in `manual_unwrap_or`, due to macro expansion
[rust.git] / tests / ui / manual_unwrap_or.rs
index 5d03d9db16392a2c10f7558441a9d14730e3c306..66006b6c616f08f9e1858e53ef451b57b26c130f 100644 (file)
@@ -1,7 +1,8 @@
 // run-rustfix
 #![allow(dead_code)]
+#![allow(unused_variables, clippy::unnecessary_wraps)]
 
-fn unwrap_or() {
+fn option_unwrap_or() {
     // int case
     match Some(1) {
         Some(i) => i,
@@ -21,13 +22,14 @@ fn unwrap_or() {
     };
 
     // multiline case
+    #[rustfmt::skip]
     match Some(1) {
         Some(i) => i,
         None => {
-            let a = 1 + 42;
-            let b = a + 42;
-            b + 42
-        },
+            42 + 42
+                + 42 + 42 + 42
+                + 42 + 42 + 42
+        }
     };
 
     // string case
@@ -55,6 +57,152 @@ fn unwrap_or() {
             None => break,
         };
     }
+
+    // cases where the none arm isn't a constant expression
+    // are not linted due to potential ownership issues
+
+    // ownership issue example, don't lint
+    struct NonCopyable;
+    let mut option: Option<NonCopyable> = None;
+    match option {
+        Some(x) => x,
+        None => {
+            option = Some(NonCopyable);
+            // some more code ...
+            option.unwrap()
+        },
+    };
+
+    // ownership issue example, don't lint
+    let option: Option<&str> = None;
+    match option {
+        Some(s) => s,
+        None => &format!("{} {}!", "hello", "world"),
+    };
+}
+
+fn result_unwrap_or() {
+    // int case
+    match Ok::<i32, &str>(1) {
+        Ok(i) => i,
+        Err(_) => 42,
+    };
+
+    // int case, scrutinee is a binding
+    let a = Ok::<i32, &str>(1);
+    match a {
+        Ok(i) => i,
+        Err(_) => 42,
+    };
+
+    // int case, suggestion must surround Result expr with parenthesis
+    match Ok(1) as Result<i32, &str> {
+        Ok(i) => i,
+        Err(_) => 42,
+    };
+
+    // method call case, suggestion must not surround Result expr `s.method()` with parenthesis
+    struct S {}
+    impl S {
+        fn method(self) -> Option<i32> {
+            Some(42)
+        }
+    }
+    let s = S {};
+    match s.method() {
+        Some(i) => i,
+        None => 42,
+    };
+
+    // int case reversed
+    match Ok::<i32, &str>(1) {
+        Err(_) => 42,
+        Ok(i) => i,
+    };
+
+    // richer none expr
+    match Ok::<i32, &str>(1) {
+        Ok(i) => i,
+        Err(_) => 1 + 42,
+    };
+
+    // multiline case
+    #[rustfmt::skip]
+    match Ok::<i32, &str>(1) {
+        Ok(i) => i,
+        Err(_) => {
+            42 + 42
+                + 42 + 42 + 42
+                + 42 + 42 + 42
+        }
+    };
+
+    // string case
+    match Ok::<&str, &str>("Bob") {
+        Ok(i) => i,
+        Err(_) => "Alice",
+    };
+
+    // don't lint
+    match Ok::<i32, &str>(1) {
+        Ok(i) => i + 2,
+        Err(_) => 42,
+    };
+    match Ok::<i32, &str>(1) {
+        Ok(i) => i,
+        Err(_) => return,
+    };
+    for j in 0..4 {
+        match Ok::<i32, &str>(j) {
+            Ok(i) => i,
+            Err(_) => continue,
+        };
+        match Ok::<i32, &str>(j) {
+            Ok(i) => i,
+            Err(_) => break,
+        };
+    }
+
+    // don't lint, Err value is used
+    match Ok::<&str, &str>("Alice") {
+        Ok(s) => s,
+        Err(s) => s,
+    };
+    // could lint, but unused_variables takes care of it
+    match Ok::<&str, &str>("Alice") {
+        Ok(s) => s,
+        Err(s) => "Bob",
+    };
+}
+
+// don't lint in const fn
+const fn const_fn_option_unwrap_or() {
+    match Some(1) {
+        Some(s) => s,
+        None => 0,
+    };
+}
+
+const fn const_fn_result_unwrap_or() {
+    match Ok::<&str, &str>("Alice") {
+        Ok(s) => s,
+        Err(_) => "Bob",
+    };
+}
+
+mod issue6965 {
+    macro_rules! some_macro {
+        () => {
+            if 1 > 2 { Some(1) } else { None }
+        };
+    }
+
+    fn test() {
+        let _ = match some_macro!() {
+            Some(val) => val,
+            None => 0,
+        };
+    }
 }
 
 fn main() {}