1
Fork 0

Handle empty loops better

This commit is contained in:
Eric Holk 2021-12-16 13:34:39 -08:00
parent 6e281a7782
commit a7df4e8d2f
3 changed files with 21 additions and 6 deletions

View file

@ -157,9 +157,16 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
} }
ExprKind::Loop(body, ..) => { ExprKind::Loop(body, ..) => {
let loop_begin = self.expr_index + 1; let loop_begin = self.expr_index + 1;
if body.stmts.is_empty() && body.expr.is_none() {
// For empty loops we won't have updated self.expr_index after visiting the
// body, meaning we'd get an edge from expr_index to expr_index + 1, but
// instead we want an edge from expr_index + 1 to expr_index + 1.
self.drop_ranges.add_control_edge(loop_begin, loop_begin);
} else {
self.visit_block(body); self.visit_block(body);
self.drop_ranges.add_control_edge(self.expr_index, loop_begin); self.drop_ranges.add_control_edge(self.expr_index, loop_begin);
} }
}
ExprKind::Break(hir::Destination { target_id: Ok(target), .. }, ..) ExprKind::Break(hir::Destination { target_id: Ok(target), .. }, ..)
| ExprKind::Continue(hir::Destination { target_id: Ok(target), .. }, ..) => { | ExprKind::Continue(hir::Destination { target_id: Ok(target), .. }, ..) => {
self.drop_ranges.add_control_edge_hir_id(self.expr_index, target); self.drop_ranges.add_control_edge_hir_id(self.expr_index, target);

View file

@ -43,6 +43,13 @@ async fn non_sync_with_method_call() {
} }
} }
async fn non_sync_with_infinite_loop() {
let f: &mut std::fmt::Formatter = loop {};
if non_sync().fmt(f).unwrap() == () {
fut().await;
}
}
fn assert_send(_: impl Send) {} fn assert_send(_: impl Send) {}
pub fn pass_assert() { pub fn pass_assert() {
@ -51,4 +58,5 @@ pub fn pass_assert() {
//~^ ERROR future cannot be sent between threads safely //~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_method_call()); assert_send(non_sync_with_method_call());
//~^ ERROR future cannot be sent between threads safely //~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_infinite_loop());
} }

View file

@ -1,5 +1,5 @@
error: future cannot be sent between threads safely error: future cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:50:17 --> $DIR/async-fn-nonsend.rs:57:17
| |
LL | assert_send(non_send_temporary_in_match()); LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
@ -16,13 +16,13 @@ LL | Some(_) => fut().await,
LL | } LL | }
| - `Some(non_send())` is later dropped here | - `Some(non_send())` is later dropped here
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/async-fn-nonsend.rs:46:24 --> $DIR/async-fn-nonsend.rs:53:24
| |
LL | fn assert_send(_: impl Send) {} LL | fn assert_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_send` | ^^^^ required by this bound in `assert_send`
error: future cannot be sent between threads safely error: future cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:52:17 --> $DIR/async-fn-nonsend.rs:59:17
| |
LL | assert_send(non_sync_with_method_call()); LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
@ -40,7 +40,7 @@ LL | }
LL | } LL | }
| - `f` is later dropped here | - `f` is later dropped here
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/async-fn-nonsend.rs:46:24 --> $DIR/async-fn-nonsend.rs:53:24
| |
LL | fn assert_send(_: impl Send) {} LL | fn assert_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_send` | ^^^^ required by this bound in `assert_send`