about summary refs log tree commit diff
path: root/tests/ui/let-else/let-else-temporary-lifetime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/let-else/let-else-temporary-lifetime.rs')
-rw-r--r--tests/ui/let-else/let-else-temporary-lifetime.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/tests/ui/let-else/let-else-temporary-lifetime.rs b/tests/ui/let-else/let-else-temporary-lifetime.rs
new file mode 100644
index 00000000000..c23eaa997fe
--- /dev/null
+++ b/tests/ui/let-else/let-else-temporary-lifetime.rs
@@ -0,0 +1,99 @@
+// run-pass
+// compile-flags: -Zvalidate-mir
+
+use std::fmt::Display;
+use std::rc::Rc;
+use std::sync::atomic::{AtomicU8, Ordering};
+
+static TRACKER: AtomicU8 = AtomicU8::new(0);
+
+#[derive(Default)]
+struct Droppy {
+    inner: u32,
+}
+
+impl Drop for Droppy {
+    fn drop(&mut self) {
+        TRACKER.store(1, Ordering::Release);
+        println!("I've been dropped");
+    }
+}
+
+fn foo<'a>(x: &'a str) -> Result<impl Display + 'a, ()> {
+    Ok(x)
+}
+
+fn main() {
+    assert_eq!(TRACKER.load(Ordering::Acquire), 0);
+    let 0 = Droppy::default().inner else { return };
+    assert_eq!(TRACKER.load(Ordering::Acquire), 1);
+    println!("Should have dropped 👆");
+
+    {
+        // cf. https://github.com/rust-lang/rust/pull/99518#issuecomment-1191520030
+        struct Foo<'a>(&'a mut u32);
+
+        impl<'a> Drop for Foo<'a> {
+            fn drop(&mut self) {
+                *self.0 = 0;
+            }
+        }
+        let mut foo = 0;
+        let Foo(0) = Foo(&mut foo) else {
+            *&mut foo = 1;
+            todo!()
+        };
+    }
+    {
+        let x = String::from("Hey");
+
+        let Ok(s) = foo(&x) else { panic!() };
+        assert_eq!(s.to_string(), x);
+    }
+    {
+        // test let-else drops temps after statement
+        let rc = Rc::new(0);
+        let 0 = *rc.clone() else { unreachable!() };
+        Rc::try_unwrap(rc).unwrap();
+    }
+    {
+        let mut rc = Rc::new(0);
+        let mut i = 0;
+        loop {
+            if i > 3 {
+                break;
+            }
+            let 1 = *rc.clone() else {
+                if let Ok(v) = Rc::try_unwrap(rc) {
+                    rc = Rc::new(v);
+                } else {
+                    panic!()
+                }
+                i += 1;
+                continue
+            };
+        }
+    }
+    {
+        fn must_pass() {
+            let rc = Rc::new(());
+            let &None = &Some(Rc::clone(&rc)) else {
+                Rc::try_unwrap(rc).unwrap();
+                return;
+            };
+            unreachable!();
+        }
+        must_pass();
+    }
+    {
+        // test let-else drops temps before else block
+        // NOTE: this test has to be the last block in the `main`
+        // body.
+        let rc = Rc::new(0);
+        let 1 = *rc.clone() else {
+            Rc::try_unwrap(rc).unwrap();
+            return;
+        };
+        unreachable!();
+    }
+}