11//@ run-pass
22//! Test drop order for different ways of declaring pattern bindings involving or-patterns.
3- //! Currently, it's inconsistent between language constructs (#142163).
3+ //! In particular, are ordered based on the order in which the first occurrence of each binding
4+ //! appears (i.e. the "primary" bindings). Regression test for #142163.
45
56use std:: cell:: RefCell ;
67use std:: ops:: Drop ;
@@ -43,11 +44,10 @@ fn main() {
4344 y = LogDrop ( o, 1 ) ;
4445 } ) ;
4546
46- // When bindings are declared with `let pat = expr;`, bindings within or-patterns are seen last,
47- // thus they're dropped first.
47+ // `let pat = expr;` should have the same drop order.
4848 assert_drop_order ( 1 ..=3 , |o| {
49- // Drops are right-to-left, treating `y` as rightmost : `y `, `z `, `x`.
50- let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 1 ) ) , LogDrop ( o, 2 ) ) ;
49+ // Drops are right-to-left: `z `, `y `, `x`.
50+ let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) ;
5151 } ) ;
5252 assert_drop_order ( 1 ..=2 , |o| {
5353 // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
@@ -58,11 +58,10 @@ fn main() {
5858 let ( ( true , x, y) | ( false , y, x) ) = ( false , LogDrop ( o, 1 ) , LogDrop ( o, 2 ) ) ;
5959 } ) ;
6060
61- // `match` treats or-patterns as last like `let pat = expr;`, but also determines drop order
62- // using the order of the bindings in the *last* or-pattern alternative.
61+ // `match` should have the same drop order.
6362 assert_drop_order ( 1 ..=3 , |o| {
64- // Drops are right-to-left, treating `y` as rightmost : `y `, `z`, `x`.
65- match ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 1 ) ) , LogDrop ( o, 2 ) ) { ( x, Ok ( y) | Err ( y) , z) => { } }
63+ // Drops are right-to-left: `z `, `y` `x`.
64+ match ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) { ( x, Ok ( y) | Err ( y) , z) => { } }
6665 } ) ;
6766 assert_drop_order ( 1 ..=2 , |o| {
6867 // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
@@ -74,27 +73,26 @@ fn main() {
7473 } ) ;
7574
7675 // Function params are visited one-by-one, and the order of bindings within a param's pattern is
77- // the same as `let pat = expr`;
76+ // the same as `let pat = expr;`
7877 assert_drop_order ( 1 ..=3 , |o| {
7978 // Among separate params, the drop order is right-to-left: `z`, `y`, `x`.
8079 ( |x, ( Ok ( y) | Err ( y) ) , z| { } ) ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) ;
8180 } ) ;
8281 assert_drop_order ( 1 ..=3 , |o| {
83- // Within a param's pattern, or-patterns are treated as rightmost : `y `, `z `, `x`.
84- ( |( x, Ok ( y) | Err ( y) , z) | { } ) ( ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 1 ) ) , LogDrop ( o, 2 ) ) ) ;
82+ // Within a param's pattern, likewise : `z `, `y `, `x`.
83+ ( |( x, Ok ( y) | Err ( y) , z) | { } ) ( ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) ) ;
8584 } ) ;
8685 assert_drop_order ( 1 ..=2 , |o| {
8786 // The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
8887 ( |( ( true , x, y) | ( false , y, x) ) | { } ) ( ( true , LogDrop ( o, 2 ) , LogDrop ( o, 1 ) ) ) ;
8988 } ) ;
9089
9190 // `if let` and `let`-`else` see bindings in the same order as `let pat = expr;`.
92- // Vars in or-patterns are seen last (dropped first), and the first alternative's order is used.
9391 assert_drop_order ( 1 ..=3 , |o| {
94- if let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 1 ) ) , LogDrop ( o, 2 ) ) { }
92+ if let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) { }
9593 } ) ;
9694 assert_drop_order ( 1 ..=3 , |o| {
97- let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 1 ) ) , LogDrop ( o, 2 ) ) else {
95+ let ( x, Ok ( y) | Err ( y) , z) = ( LogDrop ( o, 3 ) , Ok ( LogDrop ( o, 2 ) ) , LogDrop ( o, 1 ) ) else {
9896 unreachable ! ( ) ;
9997 } ;
10098 } ) ;
@@ -106,4 +104,21 @@ fn main() {
106104 unreachable ! ( ) ;
107105 } ;
108106 } ) ;
107+
108+ // Test nested and adjacent or-patterns, including or-patterns without bindings under a guard.
109+ assert_drop_order ( 1 ..=6 , |o| {
110+ // The `LogDrop`s that aren't moved into bindings are dropped last.
111+ match [
112+ [ LogDrop ( o, 6 ) , LogDrop ( o, 4 ) ] ,
113+ [ LogDrop ( o, 3 ) , LogDrop ( o, 2 ) ] ,
114+ [ LogDrop ( o, 1 ) , LogDrop ( o, 5 ) ] ,
115+ ] {
116+ [
117+ [ _ | _, w | w] | [ w | w, _ | _] ,
118+ [ x | x, y | y] | [ y | y, x | x] ,
119+ [ z | z, _ | _] | [ _ | _, z | z] ,
120+ ] if true => { }
121+ _ => unreachable ! ( ) ,
122+ }
123+ } ) ;
109124}
0 commit comments