Skip to content

Commit 84ce46a

Browse files
committed
Lower bindings in a predictable order
1 parent a4772a4 commit 84ce46a

8 files changed

+66
-96
lines changed

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

+20-50
Original file line numberDiff line numberDiff line change
@@ -43,60 +43,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4343
// let y = x;
4444
// }
4545
//
46-
// We can't just reverse the binding order, because we must preserve pattern-order
47-
// otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first,
48-
// and bindings at the same depth stay in source order.
49-
//
50-
// To do this, every time around the loop we prepend the newly found bindings to the
51-
// bindings we already had.
52-
//
53-
// example:
54-
// candidate.bindings = [1, 2, 3]
55-
// bindings in iter 1: [4, 5]
56-
// bindings in iter 2: [6, 7]
57-
//
58-
// final bindings: [6, 7, 4, 5, 1, 2, 3]
59-
let mut accumulated_bindings = mem::take(candidate_bindings);
60-
let mut simplified_match_pairs = Vec::new();
61-
// Repeatedly simplify match pairs until we're left with only unsimplifiable ones.
62-
loop {
63-
for mut match_pair in mem::take(match_pairs) {
64-
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
65-
if let Some(binding) = binding {
66-
candidate_bindings.push(binding);
67-
}
68-
if let Some(ascription) = ascription {
69-
candidate_ascriptions.push(ascription);
70-
}
71-
// Simplifiable pattern; we replace it with its subpairs and simplify further.
72-
match_pairs.append(&mut match_pair.subpairs);
73-
} else {
74-
// Unsimplifiable pattern; we recursively simplify its subpairs and don't
75-
// process it further.
76-
self.simplify_match_pairs(
77-
&mut match_pair.subpairs,
78-
candidate_bindings,
79-
candidate_ascriptions,
80-
);
81-
simplified_match_pairs.push(match_pair);
46+
// We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat`
47+
// after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
48+
// match lowering forces us to lower bindings inside or-patterns last.
49+
for mut match_pair in mem::take(match_pairs) {
50+
self.simplify_match_pairs(
51+
&mut match_pair.subpairs,
52+
candidate_bindings,
53+
candidate_ascriptions,
54+
);
55+
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
56+
if let Some(binding) = binding {
57+
candidate_bindings.push(binding);
8258
}
83-
}
84-
85-
// This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
86-
candidate_bindings.extend_from_slice(&accumulated_bindings);
87-
mem::swap(candidate_bindings, &mut accumulated_bindings);
88-
candidate_bindings.clear();
89-
90-
if match_pairs.is_empty() {
91-
break;
59+
if let Some(ascription) = ascription {
60+
candidate_ascriptions.push(ascription);
61+
}
62+
// Simplifiable pattern; we replace it with its already simplified subpairs.
63+
match_pairs.append(&mut match_pair.subpairs);
64+
} else {
65+
// Unsimplifiable pattern; we keep it.
66+
match_pairs.push(match_pair);
9267
}
9368
}
9469

95-
// Store computed bindings back in `candidate_bindings`.
96-
mem::swap(candidate_bindings, &mut accumulated_bindings);
97-
// Store simplified match pairs back in `match_pairs`.
98-
mem::swap(match_pairs, &mut simplified_match_pairs);
99-
10070
// Move or-patterns to the end, because they can result in us
10171
// creating additional candidates, so we want to test them as
10272
// late as possible.

tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@
5151
- }
5252
-
5353
- bb3: {
54-
StorageLive(_9);
55-
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
5654
StorageLive(_8);
5755
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
56+
StorageLive(_9);
57+
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
5858
_0 = const 0_u32;
59-
StorageDead(_8);
6059
StorageDead(_9);
60+
StorageDead(_8);
6161
- goto -> bb4;
6262
+ goto -> bb3;
6363
}

tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@
5757
- }
5858
-
5959
- bb4: {
60-
StorageLive(_10);
61-
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
6260
StorageLive(_9);
6361
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
62+
StorageLive(_10);
63+
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
6464
_0 = const 0_u32;
65-
StorageDead(_9);
6665
StorageDead(_10);
66+
StorageDead(_9);
6767
- goto -> bb6;
6868
+ goto -> bb4;
6969
}

tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@
5151
- }
5252
-
5353
- bb3: {
54-
StorageLive(_9);
55-
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
5654
StorageLive(_8);
5755
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
56+
StorageLive(_9);
57+
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
5858
_0 = const 0_u32;
59-
StorageDead(_8);
6059
StorageDead(_9);
60+
StorageDead(_8);
6161
- goto -> bb4;
6262
+ goto -> bb3;
6363
}

tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff

+6-6
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,16 @@
6969

7070
- bb4: {
7171
+ bb3: {
72-
StorageLive(_13);
73-
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
74-
StorageLive(_12);
75-
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
7672
StorageLive(_11);
7773
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
74+
StorageLive(_12);
75+
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
76+
StorageLive(_13);
77+
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
7878
_0 = const 0_u32;
79-
StorageDead(_11);
80-
StorageDead(_12);
8179
StorageDead(_13);
80+
StorageDead(_12);
81+
StorageDead(_11);
8282
- goto -> bb5;
8383
+ goto -> bb4;
8484
}

tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff

+24-24
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@
116116
}
117117

118118
bb6: {
119-
StorageLive(_13);
120-
_39 = deref_copy (_4.1: &ViewportPercentageLength);
121-
_13 = (((*_39) as Vw).0: f32);
122119
StorageLive(_12);
123-
_40 = deref_copy (_4.0: &ViewportPercentageLength);
124-
_12 = (((*_40) as Vw).0: f32);
120+
_39 = deref_copy (_4.0: &ViewportPercentageLength);
121+
_12 = (((*_39) as Vw).0: f32);
122+
StorageLive(_13);
123+
_40 = deref_copy (_4.1: &ViewportPercentageLength);
124+
_13 = (((*_40) as Vw).0: f32);
125125
StorageLive(_14);
126126
StorageLive(_15);
127127
_15 = _12;
@@ -132,18 +132,18 @@
132132
StorageDead(_15);
133133
_3 = ViewportPercentageLength::Vw(move _14);
134134
StorageDead(_14);
135-
StorageDead(_12);
136135
StorageDead(_13);
136+
StorageDead(_12);
137137
goto -> bb10;
138138
}
139139

140140
bb7: {
141-
StorageLive(_18);
142-
_41 = deref_copy (_4.1: &ViewportPercentageLength);
143-
_18 = (((*_41) as Vh).0: f32);
144141
StorageLive(_17);
145-
_42 = deref_copy (_4.0: &ViewportPercentageLength);
146-
_17 = (((*_42) as Vh).0: f32);
142+
_41 = deref_copy (_4.0: &ViewportPercentageLength);
143+
_17 = (((*_41) as Vh).0: f32);
144+
StorageLive(_18);
145+
_42 = deref_copy (_4.1: &ViewportPercentageLength);
146+
_18 = (((*_42) as Vh).0: f32);
147147
StorageLive(_19);
148148
StorageLive(_20);
149149
_20 = _17;
@@ -154,18 +154,18 @@
154154
StorageDead(_20);
155155
_3 = ViewportPercentageLength::Vh(move _19);
156156
StorageDead(_19);
157-
StorageDead(_17);
158157
StorageDead(_18);
158+
StorageDead(_17);
159159
goto -> bb10;
160160
}
161161

162162
bb8: {
163-
StorageLive(_23);
164-
_43 = deref_copy (_4.1: &ViewportPercentageLength);
165-
_23 = (((*_43) as Vmin).0: f32);
166163
StorageLive(_22);
167-
_44 = deref_copy (_4.0: &ViewportPercentageLength);
168-
_22 = (((*_44) as Vmin).0: f32);
164+
_43 = deref_copy (_4.0: &ViewportPercentageLength);
165+
_22 = (((*_43) as Vmin).0: f32);
166+
StorageLive(_23);
167+
_44 = deref_copy (_4.1: &ViewportPercentageLength);
168+
_23 = (((*_44) as Vmin).0: f32);
169169
StorageLive(_24);
170170
StorageLive(_25);
171171
_25 = _22;
@@ -176,18 +176,18 @@
176176
StorageDead(_25);
177177
_3 = ViewportPercentageLength::Vmin(move _24);
178178
StorageDead(_24);
179-
StorageDead(_22);
180179
StorageDead(_23);
180+
StorageDead(_22);
181181
goto -> bb10;
182182
}
183183

184184
bb9: {
185-
StorageLive(_28);
186-
_45 = deref_copy (_4.1: &ViewportPercentageLength);
187-
_28 = (((*_45) as Vmax).0: f32);
188185
StorageLive(_27);
189-
_46 = deref_copy (_4.0: &ViewportPercentageLength);
190-
_27 = (((*_46) as Vmax).0: f32);
186+
_45 = deref_copy (_4.0: &ViewportPercentageLength);
187+
_27 = (((*_45) as Vmax).0: f32);
188+
StorageLive(_28);
189+
_46 = deref_copy (_4.1: &ViewportPercentageLength);
190+
_28 = (((*_46) as Vmax).0: f32);
191191
StorageLive(_29);
192192
StorageLive(_30);
193193
_30 = _27;
@@ -198,8 +198,8 @@
198198
StorageDead(_30);
199199
_3 = ViewportPercentageLength::Vmax(move _29);
200200
StorageDead(_29);
201-
StorageDead(_27);
202201
StorageDead(_28);
202+
StorageDead(_27);
203203
goto -> bb10;
204204
}
205205

tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@
5959
}
6060

6161
bb5: {
62-
StorageLive(_10);
63-
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
6462
StorageLive(_9);
6563
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
64+
StorageLive(_10);
65+
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
6666
_0 = const 0_u32;
67-
StorageDead(_9);
6867
StorageDead(_10);
68+
StorageDead(_9);
6969
goto -> bb8;
7070
}
7171

tests/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
1919

2020
bb0: {
2121
PlaceMention(_1);
22-
_2 = discriminant((_1.2: std::option::Option<i32>));
23-
switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
22+
switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1];
2423
}
2524

2625
bb1: {
@@ -29,11 +28,12 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
2928
}
3029

3130
bb2: {
32-
switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb3, 8: bb3, otherwise: bb1];
31+
_2 = discriminant((_1.2: std::option::Option<i32>));
32+
switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1];
3333
}
3434

3535
bb3: {
36-
switchInt((_1.0: u32)) -> [1: bb4, 4: bb4, otherwise: bb1];
36+
switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1];
3737
}
3838

3939
bb4: {

0 commit comments

Comments
 (0)