about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGiles Cope <gilescope@gmail.com>2019-08-17 12:17:02 +0100
committerGiles Cope <gilescope@gmail.com>2019-08-18 10:39:15 +0100
commit1e02bc62bc72d2145a9f11c740714a1a5d94e2b4 (patch)
treea09fbbacca3e52602129f20383991b80707bdd52
parent9dd5c191993aab6c2f1538eb8ab69afdc4b6e67a (diff)
downloadrust-1e02bc62bc72d2145a9f11c740714a1a5d94e2b4.tar.gz
rust-1e02bc62bc72d2145a9f11c740714a1a5d94e2b4.zip
Better error message for break in async blocks.
-rw-r--r--src/librustc_passes/loops.rs17
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.rs5
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.stderr14
3 files changed, 23 insertions, 13 deletions
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index afe4c78dcfc..1547e607b9c 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -7,7 +7,7 @@ use rustc::ty::TyCtxt;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::{self, Node, Destination};
+use rustc::hir::{self, Node, Destination, GeneratorMovability};
 use syntax::struct_span_err;
 use syntax_pos::Span;
 use errors::Applicability;
@@ -17,6 +17,7 @@ enum Context {
     Normal,
     Loop(hir::LoopSource),
     Closure,
+    AsyncClosure,
     LabeledBlock,
     AnonConst,
 }
@@ -57,9 +58,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
             hir::ExprKind::Loop(ref b, _, source) => {
                 self.with_context(Loop(source), |v| v.visit_block(&b));
             }
-            hir::ExprKind::Closure(_, ref function_decl, b, _, _) => {
+            hir::ExprKind::Closure(_, ref function_decl, b, _, movability) => {
+                let cx = if let Some(GeneratorMovability::Static) = movability {
+                    AsyncClosure
+                } else {
+                    Closure
+                };
                 self.visit_fn_decl(&function_decl);
-                self.with_context(Closure, |v| v.visit_nested_body(b));
+                self.with_context(cx, |v| v.visit_nested_body(b));
             }
             hir::ExprKind::Block(ref b, Some(_label)) => {
                 self.with_context(LabeledBlock, |v| v.visit_block(&b));
@@ -171,6 +177,11 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
                 .span_label(span, "cannot break inside of a closure")
                 .emit();
             }
+            AsyncClosure => {
+                struct_span_err!(self.sess, span, E0267, "`{}` inside of an async block", name)
+                    .span_label(span, "cannot break inside of an async block")
+                    .emit();
+            }
             Normal | AnonConst => {
                 struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
                 .span_label(span, "cannot break outside of a loop")
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
index 6a766ede0ed..4ddcdcac822 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
@@ -32,15 +32,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
 
 fn no_break_in_async_block() {
     async {
-        break 0u8; //~ ERROR `break` inside of a closure
-        // FIXME: This diagnostic is pretty bad.
+        break 0u8; //~ ERROR `break` inside of an async block
     };
 }
 
 fn no_break_in_async_block_even_with_outer_loop() {
     loop {
         async {
-            break 0u8; //~ ERROR `break` inside of a closure
+            break 0u8; //~ ERROR `break` inside of an async block
         };
     }
 }
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
index f3f2d14584e..a0a5ac63d84 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -1,14 +1,14 @@
-error[E0267]: `break` inside of a closure
+error[E0267]: `break` inside of an async block
   --> $DIR/async-block-control-flow-static-semantics.rs:35:9
    |
 LL |         break 0u8;
-   |         ^^^^^^^^^ cannot break inside of a closure
+   |         ^^^^^^^^^ cannot break inside of an async block
 
-error[E0267]: `break` inside of a closure
-  --> $DIR/async-block-control-flow-static-semantics.rs:43:13
+error[E0267]: `break` inside of an async block
+  --> $DIR/async-block-control-flow-static-semantics.rs:42:13
    |
 LL |             break 0u8;
-   |             ^^^^^^^^^ cannot break inside of a closure
+   |             ^^^^^^^^^ cannot break inside of an async block
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:15:43
@@ -52,7 +52,7 @@ LL | async fn return_targets_async_block_not_async_fn() -> u8 {
    = note: the return type of a function must have a statically known size
 
 error[E0308]: mismatched types
-  --> $DIR/async-block-control-flow-static-semantics.rs:51:44
+  --> $DIR/async-block-control-flow-static-semantics.rs:50:44
    |
 LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
    |    ----------------------------------      ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
@@ -63,7 +63,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
               found type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/async-block-control-flow-static-semantics.rs:60:50
+  --> $DIR/async-block-control-flow-static-semantics.rs:59:50
    |
 LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
    |    ----------------------------------------      ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()