about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs11
-rw-r--r--src/test/ui/async-await/async-fn-nonsend.rs8
-rw-r--r--src/test/ui/async-await/async-fn-nonsend.stderr8
3 files changed, 21 insertions, 6 deletions
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
index 4656f56569e..b434e05db80 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
@@ -157,8 +157,15 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
             }
             ExprKind::Loop(body, ..) => {
                 let loop_begin = self.expr_index + 1;
-                self.visit_block(body);
-                self.drop_ranges.add_control_edge(self.expr_index, loop_begin);
+                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.drop_ranges.add_control_edge(self.expr_index, loop_begin);
+                }
             }
             ExprKind::Break(hir::Destination { target_id: Ok(target), .. }, ..)
             | ExprKind::Continue(hir::Destination { target_id: Ok(target), .. }, ..) => {
diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs
index 210d9ff3f2d..55629132e40 100644
--- a/src/test/ui/async-await/async-fn-nonsend.rs
+++ b/src/test/ui/async-await/async-fn-nonsend.rs
@@ -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) {}
 
 pub fn pass_assert() {
@@ -51,4 +58,5 @@ pub fn pass_assert() {
     //~^ ERROR future cannot be sent between threads safely
     assert_send(non_sync_with_method_call());
     //~^ ERROR future cannot be sent between threads safely
+    assert_send(non_sync_with_infinite_loop());
 }
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr
index abba5585c62..9c87067a4d3 100644
--- a/src/test/ui/async-await/async-fn-nonsend.stderr
+++ b/src/test/ui/async-await/async-fn-nonsend.stderr
@@ -1,5 +1,5 @@
 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());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
@@ -16,13 +16,13 @@ LL |         Some(_) => fut().await,
 LL | }
    | - `Some(non_send())` is later dropped here
 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) {}
    |                        ^^^^ required by this bound in `assert_send`
 
 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());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
@@ -40,7 +40,7 @@ LL |     }
 LL | }
    | - `f` is later dropped here
 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) {}
    |                        ^^^^ required by this bound in `assert_send`