diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index afe4c78dcfc37..1547e607b9c61 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 6a766ede0ed87..4ddcdcac82282 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 f3f2d14584ef7..a0a5ac63d8427 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 { | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () @@ -63,7 +63,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result { 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 { | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()