@@ -45,20 +45,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4545 ) -> bool {
4646 // repeatedly simplify match pairs until fixed point is reached
4747 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 ) ;
4868 let mut new_bindings = Vec :: new ( ) ;
4969 loop {
5070 let match_pairs = mem:: take ( & mut candidate. match_pairs ) ;
5171
5272 if let [ MatchPair { pattern : Pat { kind : box PatKind :: Or { pats } , .. } , place } ] =
5373 * match_pairs
5474 {
75+ exisiting_bindings. extend_from_slice ( & new_bindings) ;
76+ mem:: swap ( & mut candidate. bindings , & mut exisiting_bindings) ;
5577 candidate. subcandidates = self . create_or_subcandidates ( candidate, place, pats) ;
5678 return true ;
5779 }
5880
5981 let mut changed = false ;
6082 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) {
6284 Ok ( ( ) ) => {
6385 changed = true ;
6486 }
@@ -80,11 +102,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
80102 // let z = x.copy_field;
81103 // let y = x;
82104 // }
83- new_bindings . extend_from_slice ( & candidate . bindings ) ;
105+ candidate . bindings . extend_from_slice ( & new_bindings ) ;
84106 mem:: swap ( & mut candidate. bindings , & mut new_bindings) ;
85- new_bindings . clear ( ) ;
107+ candidate . bindings . clear ( ) ;
86108
87109 if !changed {
110+ exisiting_bindings. extend_from_slice ( & new_bindings) ;
111+ mem:: swap ( & mut candidate. bindings , & mut exisiting_bindings) ;
88112 // Move or-patterns to the end, because they can result in us
89113 // creating additional candidates, so we want to test them as
90114 // late as possible.
@@ -124,7 +148,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
124148 & mut self ,
125149 match_pair : MatchPair < ' pat , ' tcx > ,
126150 candidate : & mut Candidate < ' pat , ' tcx > ,
127- bindings : & mut Vec < Binding < ' tcx > > ,
128151 ) -> Result < ( ) , MatchPair < ' pat , ' tcx > > {
129152 let tcx = self . hir . tcx ( ) ;
130153 match * match_pair. pattern . kind {
@@ -152,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
152175 }
153176
154177 PatKind :: Binding { name, mutability, mode, var, ty, ref subpattern, is_primary : _ } => {
155- bindings. push ( Binding {
178+ candidate . bindings . push ( Binding {
156179 name,
157180 mutability,
158181 span : match_pair. pattern . span ,
0 commit comments