Skip to content

Commit 8e0c3f5

Browse files
[ci skip] Generate false edges from loop_block
As opposed to using weirdness involving pretending the body block is the loop block. This does not pass tests This commit is [ci skip] because I know it doesn't pass tests yet. Somehow this commit introduces nondeterminism into the handling of loops.
1 parent eae1a35 commit 8e0c3f5

File tree

7 files changed

+81
-67
lines changed

7 files changed

+81
-67
lines changed

src/librustc_mir/build/expr/into.rs

+22-24
Original file line numberDiff line numberDiff line change
@@ -147,24 +147,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
147147
join_block.unit()
148148
}
149149
ExprKind::Loop { condition: opt_cond_expr, body } => {
150-
// [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
151-
// ^ |
152-
// | 0
153-
// | |
154-
// | v
155-
// [body_block_end] <~~~ [body_block]
150+
// [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block]
151+
// ^ |
152+
// | 0
153+
// | |
154+
// | v
155+
// [body_block_end] <-/eval. body/-- [body_block]
156156
//
157157
// If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
158158
//
159-
// [block] --> [loop_block] ~~> [loop_block_end]
160-
// | ^ |
161-
// false link | |
162-
// | +-------------------+
163-
// v
164-
// [cleanup_block]
165-
//
166-
// The false link is required in case something results in
167-
// unwinding through the body.
159+
// [block]
160+
// |
161+
// [loop_block] -> [body_block] -/eval. body/-> [body_block_end]
162+
// | ^ |
163+
// false link | |
164+
// | +-----------------------------------------+
165+
// +-> [diverge_cleanup]
166+
// The false link is required to make sure borrowck considers unwinds through the
167+
// body, even when the exact code in the body cannot unwind
168168

169169
let loop_block = this.cfg.start_new_block();
170170
let exit_block = this.cfg.start_new_block();
@@ -178,7 +178,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
178178
move |this| {
179179
// conduct the test, if necessary
180180
let body_block;
181-
let out_terminator;
182181
if let Some(cond_expr) = opt_cond_expr {
183182
let loop_block_end;
184183
let cond = unpack!(
@@ -192,15 +191,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
192191
// we have to do it; this overwrites any `break`-assigned value but it's
193192
// always `()` anyway
194193
this.cfg.push_assign_unit(exit_block, source_info, destination);
195-
196-
out_terminator = TerminatorKind::Goto { target: loop_block };
197194
} else {
198-
body_block = loop_block;
195+
body_block = this.cfg.start_new_block();
199196
let diverge_cleanup = this.diverge_cleanup();
200-
out_terminator = TerminatorKind::FalseUnwind {
201-
real_target: loop_block,
202-
unwind: Some(diverge_cleanup)
203-
}
197+
this.cfg.terminate(loop_block, source_info,
198+
TerminatorKind::FalseUnwind {
199+
real_target: body_block,
200+
unwind: Some(diverge_cleanup)
201+
})
204202
}
205203

206204
// The “return” value of the loop body must always be an unit. We therefore
@@ -209,7 +207,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
209207
// Execute the body, branching back to the test.
210208
let body_block_end = unpack!(this.into(&tmp, body_block, body));
211209
this.cfg.terminate(body_block_end, source_info,
212-
out_terminator);
210+
TerminatorKind::Goto { target: loop_block });
213211
}
214212
);
215213
exit_block.unit()

src/test/mir-opt/end_region_2.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,29 @@ fn main() {
4040
// goto -> bb1;
4141
// }
4242
// bb1: {
43+
// falseUnwind -> [real: bb2, cleanup: bb3];
44+
// }
45+
// bb2: {
4346
// StorageLive(_2);
4447
// _2 = const true;
4548
// StorageLive(_3);
4649
// _3 = &'23_1rs _2;
4750
// StorageLive(_5);
4851
// _5 = _2;
49-
// switchInt(move _5) -> [0u8: bb4, otherwise: bb3];
52+
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
5053
// }
51-
// bb2: {
54+
// bb3: {
5255
// ...
5356
// }
54-
// bb3: {
57+
// bb4: {
5558
// _0 = ();
5659
// StorageDead(_5);
5760
// EndRegion('23_1rs);
5861
// StorageDead(_3);
5962
// StorageDead(_2);
6063
// return;
6164
// }
62-
// bb4: {
65+
// bb5: {
6366
// _4 = ();
6467
// StorageDead(_5);
6568
// StorageLive(_7);
@@ -70,6 +73,6 @@ fn main() {
7073
// EndRegion('23_1rs);
7174
// StorageDead(_3);
7275
// StorageDead(_2);
73-
// falseUnwind -> [real: bb1, cleanup: bb2];
76+
// goto -> bb1;
7477
// }
7578
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

src/test/mir-opt/end_region_3.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,28 @@ fn main() {
4343
// goto -> bb1;
4444
// }
4545
// bb1: {
46+
// falseUnwind -> [real: bb2, cleanup: bb3];
47+
// }
48+
// bb2: {
4649
// _1 = const true;
4750
// StorageLive(_3);
4851
// _3 = &'26_1rs _1;
4952
// StorageLive(_5);
5053
// _5 = _1;
51-
// switchInt(move _5) -> [0u8: bb4, otherwise: bb3];
54+
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
5255
// }
53-
// bb2: {
56+
// bb3: {
5457
// ...
5558
// }
56-
// bb3: {
59+
// bb4: {
5760
// _0 = ();
5861
// StorageDead(_5);
5962
// EndRegion('26_1rs);
6063
// StorageDead(_3);
6164
// StorageDead(_1);
6265
// return;
6366
// }
64-
// bb4: {
67+
// bb5: {
6568
// _4 = ();
6669
// StorageDead(_5);
6770
// StorageLive(_7);
@@ -71,6 +74,6 @@ fn main() {
7174
// StorageDead(_7);
7275
// EndRegion('26_1rs);
7376
// StorageDead(_3);
74-
// falseUnwind -> [real: bb1, cleanup: bb2];
77+
// goto -> bb1;
7578
// }
7679
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

src/test/mir-opt/end_region_9.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,24 @@ fn main() {
5757
// _1 = const false;
5858
// StorageLive(_2);
5959
// _2 = const 3i32;
60-
// StorageLive(_4);
61-
// goto -> bb2;
60+
// falseUnwind -> [real: bb2, cleanup: bb1];
6261
// }
6362
// bb1: {
6463
// ...
6564
// }
6665
// bb2: {
66+
// StorageLive(_4);
67+
// goto -> bb3;
68+
// }
69+
// bb3: {
70+
// falseUnwind -> [real: bb4, cleanup: bb1];
71+
// }
72+
// bb4: {
6773
// StorageLive(_7);
6874
// _7 = _1;
69-
// switchInt(move _7) -> [0u8: bb4, otherwise: bb3];
75+
// switchInt(move _7) -> [0u8: bb6, otherwise: bb5];
7076
// }
71-
// bb3: {
77+
// bb5: {
7278
// _0 = ();
7379
// StorageDead(_7);
7480
// EndRegion('33_0rs);
@@ -77,13 +83,13 @@ fn main() {
7783
// StorageDead(_1);
7884
// return;
7985
// }
80-
// bb4: {
86+
// bb6: {
8187
// _4 = &'33_0rs _2;
8288
// _6 = ();
8389
// StorageDead(_7);
8490
// _1 = const true;
8591
// _3 = ();
86-
// falseUnwind -> [real: bb2, cleanup: bb1];
92+
// goto -> bb3;
8793
// }
8894
// }
8995
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

src/test/mir-opt/end_region_cyclic.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,19 @@ fn query() -> bool { true }
6767
// goto -> bb1;
6868
// }
6969
// bb1: {
70+
// falseUnwind -> [real: bb2, cleanup: bb3];
71+
// }
72+
// bb2: {
7073
// StorageLive(_2);
7174
// StorageLive(_3);
7275
// StorageLive(_4);
7376
// _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
74-
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb3, unwind: bb2];
77+
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
7578
// }
76-
// bb2: {
79+
// bb3: {
7780
// resume;
7881
// }
79-
// bb3: {
82+
// bb4: {
8083
// StorageDead(_4);
8184
// _2 = S<'35_0rs> { r: move _3 };
8285
// StorageDead(_3);
@@ -89,27 +92,27 @@ fn query() -> bool { true }
8992
// _8 = &'35_0rs (*_9);
9093
// _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
9194
// StorageDead(_8);
92-
// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb4, unwind: bb2];
95+
// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
9396
// }
94-
// bb4: {
97+
// bb5: {
9598
// EndRegion('16s);
9699
// StorageDead(_7);
97100
// StorageDead(_6);
98101
// StorageDead(_9);
99102
// StorageLive(_11);
100-
// _11 = const query() -> [return: bb5, unwind: bb2];
101-
// }
102-
// bb5: {
103-
// switchInt(move _11) -> [0u8: bb7, otherwise: bb6];
103+
// _11 = const query() -> [return: bb6, unwind: bb3];
104104
// }
105105
// bb6: {
106+
// switchInt(move _11) -> [0u8: bb8, otherwise: bb7];
107+
// }
108+
// bb7: {
106109
// _0 = ();
107110
// StorageDead(_11);
108111
// EndRegion('35_0rs);
109112
// StorageDead(_2);
110113
// return;
111114
// }
112-
// bb7: {
115+
// bb8: {
113116
// _10 = ();
114117
// StorageDead(_11);
115118
// StorageLive(_14);
@@ -121,17 +124,17 @@ fn query() -> bool { true }
121124
// _16 = &'35_0rs (*_17);
122125
// _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
123126
// StorageDead(_16);
124-
// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb8, unwind: bb2];
127+
// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
125128
// }
126-
// bb8: {
129+
// bb9: {
127130
// EndRegion('33s);
128131
// StorageDead(_15);
129132
// StorageDead(_14);
130133
// StorageDead(_17);
131134
// _1 = ();
132135
// EndRegion('35_0rs);
133136
// StorageDead(_2);
134-
// falseUnwind -> [real: bb1, cleanup: bb2];
137+
// goto -> bb1;
135138
// }
136139
// }
137140
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

src/test/mir-opt/issue-38669.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,28 @@ fn main() {
2727
// _1 = const false;
2828
// goto -> bb2;
2929
// }
30-
//
3130
// bb1: {
3231
// resume;
3332
// }
3433
// bb2: {
34+
// falseUnwind -> [real: bb3, cleanup: bb1];
35+
// }
36+
// bb3: {
3537
// StorageLive(_4);
3638
// _4 = _1;
37-
// switchInt(move _4) -> [0u8: bb4, otherwise: bb3];
39+
// switchInt(move _4) -> [0u8: bb5, otherwise: bb4];
3840
// }
39-
// bb3: {
41+
// bb4: {
4042
// _0 = ();
4143
// StorageDead(_4);
4244
// StorageDead(_1);
4345
// return;
4446
// }
45-
//
46-
// bb4: {
47+
// bb5: {
4748
// _3 = ();
4849
// StorageDead(_4);
4950
// _1 = const true;
5051
// _2 = ();
51-
// falseUnwind -> [real: bb2, cleanup: bb1];
52+
// goto -> bb2;
5253
// }
5354
// END rustc.main.SimplifyCfg-initial.after.mir

src/test/mir-opt/nll/liveness-drop-intra-block.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ fn main() {
2525

2626
// END RUST SOURCE
2727
// START rustc.main.nll.0.mir
28-
// | Live variables on entry to bb2: []
29-
// bb2: {
30-
// | Live variables on entry to bb2[0]: []
28+
// | Live variables on entry to bb3: []
29+
// bb3: {
30+
// | Live variables on entry to bb3[0]: []
3131
// _1 = const 55usize;
32-
// | Live variables on entry to bb2[1]: [_1]
32+
// | Live variables on entry to bb3[1]: [_1]
3333
// StorageLive(_3);
34-
// | Live variables on entry to bb2[2]: [_1]
34+
// | Live variables on entry to bb3[2]: [_1]
3535
// StorageLive(_4);
36-
// | Live variables on entry to bb2[3]: [_1]
36+
// | Live variables on entry to bb3[3]: [_1]
3737
// _4 = _1;
38-
// | Live variables on entry to bb2[4]: [_4]
39-
// _3 = const use_x(move _4) -> [return: bb3, unwind: bb1];
38+
// | Live variables on entry to bb3[4]: [_4]
39+
// _3 = const use_x(move _4) -> [return: bb4, unwind: bb1];
4040
// }
4141
// END rustc.main.nll.0.mir

0 commit comments

Comments
 (0)