Skip to content

Commit ed6a2eb

Browse files
mir: Add false edge cleanup out of infinite loops
Fixes #46036
1 parent bdc37aa commit ed6a2eb

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

src/librustc_mir/build/expr/into.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
156156
//
157157
// If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
158158
//
159-
// [block] --> [loop_block / body_block ] ~~> [body_block_end] [exit_block]
160-
// ^ |
161-
// | |
162-
// +--------------------------+
159+
// [block] --> [loop_block] ~~> [loop_block_end]
160+
// | ^ |
161+
// false link | |
162+
// | +-------------------+
163+
// v
164+
// [cleanup_block]
163165
//
166+
// The false link is required in case something results in
167+
// unwinding through the body.
164168

165169
let loop_block = this.cfg.start_new_block();
166170
let exit_block = this.cfg.start_new_block();
@@ -174,6 +178,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
174178
move |this| {
175179
// conduct the test, if necessary
176180
let body_block;
181+
let out_terminator;
177182
if let Some(cond_expr) = opt_cond_expr {
178183
let loop_block_end;
179184
let cond = unpack!(
@@ -187,8 +192,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
187192
// we have to do it; this overwrites any `break`-assigned value but it's
188193
// always `()` anyway
189194
this.cfg.push_assign_unit(exit_block, source_info, destination);
195+
196+
out_terminator = TerminatorKind::Goto { target: loop_block };
190197
} else {
191198
body_block = loop_block;
199+
let diverge_cleanup = this.diverge_cleanup();
200+
out_terminator = TerminatorKind::FalseUnwind {
201+
real_target: loop_block,
202+
unwind: Some(diverge_cleanup)
203+
}
192204
}
193205

194206
// The “return” value of the loop body must always be an unit. We therefore
@@ -197,7 +209,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
197209
// Execute the body, branching back to the test.
198210
let body_block_end = unpack!(this.into(&tmp, body_block, body));
199211
this.cfg.terminate(body_block_end, source_info,
200-
TerminatorKind::Goto { target: loop_block });
212+
out_terminator);
201213
}
202214
);
203215
exit_block.unit()

0 commit comments

Comments
 (0)