about summary refs log tree commit diff
path: root/tests/ui/drop/or-pattern-drop-order.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/drop/or-pattern-drop-order.rs')
-rw-r--r--tests/ui/drop/or-pattern-drop-order.rs45
1 files changed, 30 insertions, 15 deletions
diff --git a/tests/ui/drop/or-pattern-drop-order.rs b/tests/ui/drop/or-pattern-drop-order.rs
index a4e4d24995b..cca81673ac3 100644
--- a/tests/ui/drop/or-pattern-drop-order.rs
+++ b/tests/ui/drop/or-pattern-drop-order.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 //! Test drop order for different ways of declaring pattern bindings involving or-patterns.
-//! Currently, it's inconsistent between language constructs (#142163).
+//! In particular, are ordered based on the order in which the first occurrence of each binding
+//! appears (i.e. the "primary" bindings). Regression test for #142163.
 
 use std::cell::RefCell;
 use std::ops::Drop;
@@ -43,11 +44,10 @@ fn main() {
         y = LogDrop(o, 1);
     });
 
-    // When bindings are declared with `let pat = expr;`, bindings within or-patterns are seen last,
-    // thus they're dropped first.
+    // `let pat = expr;` should have the same drop order.
     assert_drop_order(1..=3, |o| {
-        // Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`.
-        let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2));
+        // Drops are right-to-left: `z`, `y`, `x`.
+        let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1));
     });
     assert_drop_order(1..=2, |o| {
         // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
@@ -58,11 +58,10 @@ fn main() {
         let ((true, x, y) | (false, y, x)) = (false, LogDrop(o, 1), LogDrop(o, 2));
     });
 
-    // `match` treats or-patterns as last like `let pat = expr;`, but also determines drop order
-    // using the order of the bindings in the *last* or-pattern alternative.
+    // `match` should have the same drop order.
     assert_drop_order(1..=3, |o| {
-        // Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`.
-        match (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) { (x, Ok(y) | Err(y), z) => {} }
+        // Drops are right-to-left: `z`, `y` `x`.
+        match (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) { (x, Ok(y) | Err(y), z) => {} }
     });
     assert_drop_order(1..=2, |o| {
         // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
@@ -74,14 +73,14 @@ fn main() {
     });
 
     // Function params are visited one-by-one, and the order of bindings within a param's pattern is
-    // the same as `let pat = expr`;
+    // the same as `let pat = expr;`
     assert_drop_order(1..=3, |o| {
         // Among separate params, the drop order is right-to-left: `z`, `y`, `x`.
         (|x, (Ok(y) | Err(y)), z| {})(LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1));
     });
     assert_drop_order(1..=3, |o| {
-        // Within a param's pattern, or-patterns are treated as rightmost: `y`, `z`, `x`.
-        (|(x, Ok(y) | Err(y), z)| {})((LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)));
+        // Within a param's pattern, likewise: `z`, `y`, `x`.
+        (|(x, Ok(y) | Err(y), z)| {})((LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)));
     });
     assert_drop_order(1..=2, |o| {
         // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
@@ -89,12 +88,11 @@ fn main() {
     });
 
     // `if let` and `let`-`else` see bindings in the same order as `let pat = expr;`.
-    // Vars in or-patterns are seen last (dropped first), and the first alternative's order is used.
     assert_drop_order(1..=3, |o| {
-        if let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) {}
+        if let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) {}
     });
     assert_drop_order(1..=3, |o| {
-        let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) else {
+        let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) else {
             unreachable!();
         };
     });
@@ -106,4 +104,21 @@ fn main() {
             unreachable!();
         };
     });
+
+    // Test nested and adjacent or-patterns, including or-patterns without bindings under a guard.
+    assert_drop_order(1..=6, |o| {
+        // The `LogDrop`s that aren't moved into bindings are dropped last.
+        match [
+            [LogDrop(o, 6), LogDrop(o, 4)],
+            [LogDrop(o, 3), LogDrop(o, 2)],
+            [LogDrop(o, 1), LogDrop(o, 5)],
+        ] {
+            [
+                [_ | _, w | w] | [w | w, _ | _],
+                [x | x, y | y] | [y | y, x | x],
+                [z | z, _ | _] | [_ | _, z | z],
+            ] if true => {}
+            _ => unreachable!(),
+        }
+    });
 }