@@ -45,20 +45,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
45
45
) -> bool {
46
46
// repeatedly simplify match pairs until fixed point is reached
47
47
debug ! ( "simplify_candidate(candidate={:?})" , candidate) ;
48
+
49
+ // exisiting_bindings and new_bindings exists to keep the semantics in order
50
+ // reversing the binding order for bindings after `@` change binding order in places
51
+ // it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)`
52
+ //
53
+ // To avoid this, the binding occurs in the following manner:
54
+ // * the bindings for one iteration of the following loop occurs in order (i.e. left to
55
+ // right)
56
+ // * the bindings from the previous iteration of the loop is prepended to the bindings from
57
+ // the current iteration (in the implementation this is done by mem::swap and extend)
58
+ // * after all iterations, these new bindings are then appended to the bindings that were
59
+ // prexisting (i.e. `candidate.binding` when the function was called).
60
+ //
61
+ // example:
62
+ // candidate.bindings = [1, 2, 3]
63
+ // binding in iter 1: [4, 5]
64
+ // binding in iter 2: [6, 7]
65
+ //
66
+ // final binding: [1, 2, 3, 6, 7, 4, 5]
67
+ let mut exisiting_bindings = mem:: take ( & mut candidate. bindings ) ;
48
68
let mut new_bindings = Vec :: new ( ) ;
49
69
loop {
50
70
let match_pairs = mem:: take ( & mut candidate. match_pairs ) ;
51
71
52
72
if let [ MatchPair { pattern : Pat { kind : box PatKind :: Or { pats } , .. } , place } ] =
53
73
* match_pairs
54
74
{
75
+ exisiting_bindings. extend_from_slice ( & new_bindings) ;
76
+ mem:: swap ( & mut candidate. bindings , & mut exisiting_bindings) ;
55
77
candidate. subcandidates = self . create_or_subcandidates ( candidate, place, pats) ;
56
78
return true ;
57
79
}
58
80
59
81
let mut changed = false ;
60
82
for match_pair in match_pairs {
61
- match self . simplify_match_pair ( match_pair, candidate, & mut new_bindings ) {
83
+ match self . simplify_match_pair ( match_pair, candidate) {
62
84
Ok ( ( ) ) => {
63
85
changed = true ;
64
86
}
@@ -80,11 +102,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
80
102
// let z = x.copy_field;
81
103
// let y = x;
82
104
// }
83
- new_bindings . extend_from_slice ( & candidate . bindings ) ;
105
+ candidate . bindings . extend_from_slice ( & new_bindings ) ;
84
106
mem:: swap ( & mut candidate. bindings , & mut new_bindings) ;
85
- new_bindings . clear ( ) ;
107
+ candidate . bindings . clear ( ) ;
86
108
87
109
if !changed {
110
+ exisiting_bindings. extend_from_slice ( & new_bindings) ;
111
+ mem:: swap ( & mut candidate. bindings , & mut exisiting_bindings) ;
88
112
// Move or-patterns to the end, because they can result in us
89
113
// creating additional candidates, so we want to test them as
90
114
// late as possible.
@@ -124,7 +148,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
124
148
& mut self ,
125
149
match_pair : MatchPair < ' pat , ' tcx > ,
126
150
candidate : & mut Candidate < ' pat , ' tcx > ,
127
- bindings : & mut Vec < Binding < ' tcx > > ,
128
151
) -> Result < ( ) , MatchPair < ' pat , ' tcx > > {
129
152
let tcx = self . hir . tcx ( ) ;
130
153
match * match_pair. pattern . kind {
@@ -152,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
152
175
}
153
176
154
177
PatKind :: Binding { name, mutability, mode, var, ty, ref subpattern, is_primary : _ } => {
155
- bindings. push ( Binding {
178
+ candidate . bindings . push ( Binding {
156
179
name,
157
180
mutability,
158
181
span : match_pair. pattern . span ,
0 commit comments