Skip to content

Commit 47c4e8c

Browse files
committed
Add a test for match scopes
1 parent 4a6ba51 commit 47c4e8c

File tree

1 file changed

+245
-0
lines changed

1 file changed

+245
-0
lines changed

src/test/mir-opt/match-arm-scopes.rs

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// Test that StorageDead and Drops are generated properly for bindings in
2+
// matches:
3+
// * The MIR should only contain a single drop of `s` and `t`: at the end
4+
// of their respective arms.
5+
// * StorageDead and StorageLive statements are correctly matched up on
6+
// non-unwind paths.
7+
// * The visibility scopes of the match arms should be disjoint, and contain.
8+
// all of the bindings for that scope.
9+
// * No drop flags are used.
10+
11+
#![feature(nll, bind_by_move_pattern_guards)]
12+
13+
fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 {
14+
match items {
15+
(false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1,
16+
(true, b, t) | (false, b, t) => 2,
17+
}
18+
}
19+
20+
const CASES: &[(bool, bool, bool, i32)] = &[
21+
(false, false, false, 2),
22+
(false, false, true, 1),
23+
(false, true, false, 1),
24+
(false, true, true, 2),
25+
(true, false, false, 3),
26+
(true, false, true, 3),
27+
(true, true, false, 3),
28+
(true, true, true, 2),
29+
];
30+
31+
fn main() {
32+
for &(cond, items_1, items_2, result) in CASES {
33+
assert_eq!(
34+
complicated_match(cond, (items_1, items_2, String::new())),
35+
result,
36+
);
37+
}
38+
}
39+
40+
// END RUST SOURCE
41+
// START rustc.complicated_match.SimplifyCfg-initial.after.mir
42+
// let mut _0: i32;
43+
// let mut _3: &bool; // Temp for fake borrow of `items.0`
44+
// let mut _4: &bool; // Temp for fake borrow of `items.1`
45+
// let _5: bool; // `a` in arm
46+
// let _6: &bool; // `a` in guard
47+
// let _7: std::string::String; // `s` in arm
48+
// let _8: &std::string::String; // `s` in guard
49+
// let mut _9: bool; // `if cond { return 3 } else { a }`
50+
// let mut _10: bool; // `cond`
51+
// let mut _11: !; // `return 3`
52+
// let mut _12: bool; // `if cond { return 3 } else { a }`
53+
// let mut _13: bool; // `cond`
54+
// let mut _14: !; // `return 3`
55+
// let _15: bool; // `b`
56+
// let _16: std::string::String; // `t`
57+
// scope 1 {
58+
// }
59+
// scope 2 {
60+
// }
61+
// bb0: {
62+
// FakeRead(ForMatchedPlace, _2);
63+
// switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb7];
64+
// }
65+
// bb1 (cleanup): {
66+
// resume;
67+
// }
68+
// bb2: {
69+
// falseEdges -> [real: bb10, imaginary: bb3];
70+
// }
71+
// bb3: {
72+
// falseEdges -> [real: bb21, imaginary: bb4];
73+
// }
74+
// bb4: {
75+
// falseEdges -> [real: bb31, imaginary: bb5];
76+
// }
77+
// bb5: {
78+
// falseEdges -> [real: bb32, imaginary: bb6];
79+
// }
80+
// bb6: {
81+
// unreachable;
82+
// }
83+
// bb7: {
84+
// switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb8];
85+
// }
86+
// bb8: {
87+
// switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb4];
88+
// }
89+
// bb9: { // arm 1
90+
// _0 = const 1i32;
91+
// drop(_7) -> [return: bb29, unwind: bb16];
92+
// }
93+
// bb10: { // guard - first time
94+
// StorageLive(_6);
95+
// _6 = &(_2.1: bool);
96+
// StorageLive(_8);
97+
// _8 = &(_2.2: std::string::String);
98+
// _3 = &shallow (_2.0: bool);
99+
// _4 = &shallow (_2.1: bool);
100+
// StorageLive(_9);
101+
// StorageLive(_10);
102+
// _10 = _1;
103+
// FakeRead(ForMatchedPlace, _10);
104+
// switchInt(_10) -> [false: bb12, otherwise: bb11];
105+
// }
106+
// bb11: {
107+
// falseEdges -> [real: bb14, imaginary: bb12];
108+
// }
109+
// bb12: {
110+
// falseEdges -> [real: bb18, imaginary: bb13];
111+
// }
112+
// bb13: {
113+
// unreachable;
114+
// }
115+
// bb14: { // `return 3` - first time
116+
// _0 = const 3i32;
117+
// StorageDead(_10);
118+
// StorageDead(_9);
119+
// StorageDead(_8);
120+
// StorageDead(_6);
121+
// goto -> bb17;
122+
// }
123+
// bb15: {
124+
// return;
125+
// }
126+
// bb16 (cleanup): {
127+
// drop(_2) -> bb1;
128+
// }
129+
// bb17: {
130+
// drop(_2) -> [return: bb15, unwind: bb1];
131+
// }
132+
// bb18: { // `else` block - first time
133+
// _9 = (*_6);
134+
// StorageDead(_10);
135+
// FakeRead(ForMatchGuard, _3);
136+
// FakeRead(ForMatchGuard, _4);
137+
// FakeRead(ForGuardBinding, _6);
138+
// FakeRead(ForGuardBinding, _8);
139+
// switchInt(move _9) -> [false: bb20, otherwise: bb19];
140+
// }
141+
// bb19: {
142+
// StorageDead(_9);
143+
// StorageLive(_5);
144+
// _5 = (_2.1: bool);
145+
// StorageLive(_7);
146+
// _7 = move (_2.2: std::string::String);
147+
// goto -> bb9;
148+
// }
149+
// bb20: { // guard otherwise case - first time
150+
// StorageDead(_9);
151+
// StorageDead(_8);
152+
// StorageDead(_6);
153+
// falseEdges -> [real: bb7, imaginary: bb3];
154+
// }
155+
// bb21: { // guard - second time
156+
// StorageLive(_6);
157+
// _6 = &(_2.0: bool);
158+
// StorageLive(_8);
159+
// _8 = &(_2.2: std::string::String);
160+
// _3 = &shallow (_2.0: bool);
161+
// _4 = &shallow (_2.1: bool);
162+
// StorageLive(_12);
163+
// StorageLive(_13);
164+
// _13 = _1;
165+
// FakeRead(ForMatchedPlace, _13);
166+
// switchInt(_13) -> [false: bb23, otherwise: bb22];
167+
// }
168+
// bb22: {
169+
// falseEdges -> [real: bb25, imaginary: bb23];
170+
// }
171+
// bb23: {
172+
// falseEdges -> [real: bb26, imaginary: bb24];
173+
// }
174+
// bb24: {
175+
// unreachable;
176+
// }
177+
// bb25: { // `return 3` - second time
178+
// _0 = const 3i32;
179+
// StorageDead(_13);
180+
// StorageDead(_12);
181+
// StorageDead(_8);
182+
// StorageDead(_6);
183+
// goto -> bb17;
184+
// }
185+
// bb26: { // `else` block - second time
186+
// _12 = (*_6);
187+
// StorageDead(_13);
188+
// FakeRead(ForMatchGuard, _3);
189+
// FakeRead(ForMatchGuard, _4);
190+
// FakeRead(ForGuardBinding, _6);
191+
// FakeRead(ForGuardBinding, _8);
192+
// switchInt(move _12) -> [false: bb28, otherwise: bb27];
193+
// }
194+
// bb27: { // Guard otherwise case - second time
195+
// StorageDead(_12);
196+
// StorageLive(_5);
197+
// _5 = (_2.0: bool);
198+
// StorageLive(_7);
199+
// _7 = move (_2.2: std::string::String);
200+
// goto -> bb9;
201+
// }
202+
// bb28: { // rest of arm 1
203+
// StorageDead(_12);
204+
// StorageDead(_8);
205+
// StorageDead(_6);
206+
// falseEdges -> [real: bb8, imaginary: bb4];
207+
// }
208+
// bb29: {
209+
// StorageDead(_7);
210+
// StorageDead(_5);
211+
// StorageDead(_8);
212+
// StorageDead(_6);
213+
// goto -> bb34;
214+
// }
215+
// bb30: { // arm 2
216+
// _0 = const 2i32;
217+
// drop(_16) -> [return: bb33, unwind: bb16];
218+
// }
219+
// bb31: { // bindings for arm 2 - first pattern
220+
// StorageLive(_15);
221+
// _15 = (_2.1: bool);
222+
// StorageLive(_16);
223+
// _16 = move (_2.2: std::string::String);
224+
// goto -> bb30;
225+
// }
226+
// bb32: { // bindings for arm 2 - first pattern
227+
// StorageLive(_15);
228+
// _15 = (_2.1: bool);
229+
// StorageLive(_16);
230+
// _16 = move (_2.2: std::string::String);
231+
// goto -> bb30;
232+
// }
233+
// bb33: { // rest of arm 2
234+
// StorageDead(_16);
235+
// StorageDead(_15);
236+
// goto -> bb34;
237+
// }
238+
// bb34: { // end of match
239+
// drop(_2) -> [return: bb15, unwind: bb1];
240+
// }
241+
// END rustc.complicated_match.SimplifyCfg-initial.after.mir
242+
// START rustc.complicated_match.ElaborateDrops.after.mir
243+
// let _16: std::string::String; // No drop flags, which would come after this.
244+
// scope 1 {
245+
// END rustc.complicated_match.ElaborateDrops.after.mir

0 commit comments

Comments
 (0)