about summary refs log tree commit diff
path: root/tests/ui/drop/drop-order-comparisons-let-chains.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/drop/drop-order-comparisons-let-chains.rs')
-rw-r--r--tests/ui/drop/drop-order-comparisons-let-chains.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/tests/ui/drop/drop-order-comparisons-let-chains.rs b/tests/ui/drop/drop-order-comparisons-let-chains.rs
new file mode 100644
index 00000000000..5dea5e1a580
--- /dev/null
+++ b/tests/ui/drop/drop-order-comparisons-let-chains.rs
@@ -0,0 +1,145 @@
+// See drop-order-comparisons.rs
+
+//@ edition: 2024
+//@ run-pass
+
+#![feature(if_let_guard)]
+
+fn t_if_let_chains_then() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(8)
+        && let Ok(_) = e.ok(7)
+        && let Ok(_) = e.ok(6).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(5)
+        && let Ok(_) = e.ok(4).as_ref() {
+            e.mark(3);
+        };
+    e.assert(9);
+}
+
+fn t_guard_if_let_chains_then() {
+    let e = Events::new();
+    _ = match () {
+        () if e.ok(1).is_ok()
+            && let true = e.ok(9).is_ok()
+            && let Ok(_v) = e.ok(8)
+            && let Ok(_) = e.ok(7)
+            && let Ok(_) = e.ok(6).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(5)
+            && let Ok(_) = e.ok(4).as_ref() => {
+                e.mark(3);
+            }
+        _ => {}
+    };
+    e.assert(9);
+}
+
+fn t_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(8).is_ok()
+        && let Ok(_v) = e.ok(7)
+        && let Ok(_) = e.ok(6)
+        && let Ok(_) = e.ok(5).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.err(3) {} else {
+            e.mark(9);
+        };
+    e.assert(9);
+}
+
+fn t_guard_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = match () {
+       () if e.ok(1).is_ok()
+            && let true = e.ok(8).is_ok()
+            && let Ok(_v) = e.ok(7)
+            && let Ok(_) = e.ok(6)
+            && let Ok(_) = e.ok(5).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(4)
+            && let Ok(_) = e.err(3) => {}
+        _ => {
+            e.mark(9);
+        }
+    };
+    e.assert(9);
+}
+
+fn main() {
+    t_if_let_chains_then();
+    t_guard_if_let_chains_then();
+    t_if_let_chains_then_else();
+    t_guard_if_let_chains_then_else();
+}
+
+// # Test scaffolding
+
+use core::cell::RefCell;
+use std::collections::HashSet;
+
+/// A buffer to track the order of events.
+///
+/// First, numbered events are logged into this buffer.
+///
+/// Then, `assert` is called to verify that the correct number of
+/// events were logged, and that they were logged in the expected
+/// order.
+struct Events(RefCell<Option<Vec<u64>>>);
+
+impl Events {
+    const fn new() -> Self {
+        Self(RefCell::new(Some(Vec::new())))
+    }
+    #[track_caller]
+    fn assert(&self, max: u64) {
+        let buf = &self.0;
+        let v1 = buf.borrow().as_ref().unwrap().clone();
+        let mut v2 = buf.borrow().as_ref().unwrap().clone();
+        *buf.borrow_mut() = None;
+        v2.sort();
+        let uniq_len = v2.iter().collect::<HashSet<_>>().len();
+        // Check that the sequence is sorted.
+        assert_eq!(v1, v2);
+        // Check that there are no duplicates.
+        assert_eq!(v2.len(), uniq_len);
+        // Check that the length is the expected one.
+        assert_eq!(max, uniq_len as u64);
+        // Check that the last marker is the expected one.
+        assert_eq!(v2.last().unwrap(), &max);
+    }
+    /// Return an `Ok` value that logs its drop.
+    fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
+        Ok(LogDrop(self, m))
+    }
+    /// Return an `Err` value that logs its drop.
+    fn err(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
+        Err(LogDrop(self, m))
+    }
+    /// Log an event.
+    fn mark(&self, m: u64) {
+        self.0.borrow_mut().as_mut().unwrap().push(m);
+    }
+}
+
+impl Drop for Events {
+    fn drop(&mut self) {
+        if self.0.borrow().is_some() {
+            panic!("failed to call `Events::assert()`");
+        }
+    }
+}
+
+/// A type that logs its drop events.
+struct LogDrop<'b>(&'b Events, u64);
+
+impl<'b> Drop for LogDrop<'b> {
+    fn drop(&mut self) {
+        self.0.mark(self.1);
+    }
+}