Skip to content

Commit f422e81

Browse files
committed
preserve bindings order for Some
1 parent 6bdce7b commit f422e81

19 files changed

+239
-258
lines changed

compiler/rustc_mir_build/src/build/matches/simplify.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -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,

src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@
5252
- }
5353
-
5454
- bb3: {
55-
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
56-
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
5755
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
5856
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
57+
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
58+
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
5959
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:5:31: 5:32
60-
StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
6160
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
61+
StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
6262
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
6363
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
6464
}

src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@
5959
-
6060
- bb4: {
6161
+ bb2: {
62-
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
63-
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
6462
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
6563
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
64+
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
65+
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
6666
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
67-
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
6867
StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
68+
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
6969
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
7070
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
7171
}

src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff

+6-6
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,16 @@
7171

7272
- bb4: {
7373
+ bb3: {
74-
StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:33: 6:34
75-
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:33: 6:34
76-
StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:24: 6:25
77-
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:24: 6:25
7874
StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:15: 6:16
7975
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:15: 6:16
76+
StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:24: 6:25
77+
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:24: 6:25
78+
StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:33: 6:34
79+
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:33: 6:34
8080
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
81-
StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
82-
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
8381
StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
82+
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
83+
StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
8484
- goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
8585
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
8686
}

0 commit comments

Comments
 (0)