Skip to content

Commit a7df4e8

Browse files
committed
Handle empty loops better
1 parent 6e281a7 commit a7df4e8

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,15 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
157157
}
158158
ExprKind::Loop(body, ..) => {
159159
let loop_begin = self.expr_index + 1;
160-
self.visit_block(body);
161-
self.drop_ranges.add_control_edge(self.expr_index, loop_begin);
160+
if body.stmts.is_empty() && body.expr.is_none() {
161+
// For empty loops we won't have updated self.expr_index after visiting the
162+
// body, meaning we'd get an edge from expr_index to expr_index + 1, but
163+
// instead we want an edge from expr_index + 1 to expr_index + 1.
164+
self.drop_ranges.add_control_edge(loop_begin, loop_begin);
165+
} else {
166+
self.visit_block(body);
167+
self.drop_ranges.add_control_edge(self.expr_index, loop_begin);
168+
}
162169
}
163170
ExprKind::Break(hir::Destination { target_id: Ok(target), .. }, ..)
164171
| ExprKind::Continue(hir::Destination { target_id: Ok(target), .. }, ..) => {

src/test/ui/async-await/async-fn-nonsend.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ async fn non_sync_with_method_call() {
4343
}
4444
}
4545

46+
async fn non_sync_with_infinite_loop() {
47+
let f: &mut std::fmt::Formatter = loop {};
48+
if non_sync().fmt(f).unwrap() == () {
49+
fut().await;
50+
}
51+
}
52+
4653
fn assert_send(_: impl Send) {}
4754

4855
pub fn pass_assert() {
@@ -51,4 +58,5 @@ pub fn pass_assert() {
5158
//~^ ERROR future cannot be sent between threads safely
5259
assert_send(non_sync_with_method_call());
5360
//~^ ERROR future cannot be sent between threads safely
61+
assert_send(non_sync_with_infinite_loop());
5462
}

src/test/ui/async-await/async-fn-nonsend.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: future cannot be sent between threads safely
2-
--> $DIR/async-fn-nonsend.rs:50:17
2+
--> $DIR/async-fn-nonsend.rs:57:17
33
|
44
LL | assert_send(non_send_temporary_in_match());
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
@@ -16,13 +16,13 @@ LL | Some(_) => fut().await,
1616
LL | }
1717
| - `Some(non_send())` is later dropped here
1818
note: required by a bound in `assert_send`
19-
--> $DIR/async-fn-nonsend.rs:46:24
19+
--> $DIR/async-fn-nonsend.rs:53:24
2020
|
2121
LL | fn assert_send(_: impl Send) {}
2222
| ^^^^ required by this bound in `assert_send`
2323

2424
error: future cannot be sent between threads safely
25-
--> $DIR/async-fn-nonsend.rs:52:17
25+
--> $DIR/async-fn-nonsend.rs:59:17
2626
|
2727
LL | assert_send(non_sync_with_method_call());
2828
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
@@ -40,7 +40,7 @@ LL | }
4040
LL | }
4141
| - `f` is later dropped here
4242
note: required by a bound in `assert_send`
43-
--> $DIR/async-fn-nonsend.rs:46:24
43+
--> $DIR/async-fn-nonsend.rs:53:24
4444
|
4545
LL | fn assert_send(_: impl Send) {}
4646
| ^^^^ required by this bound in `assert_send`

0 commit comments

Comments
 (0)