Better error message for break in async blocks.

This commit is contained in:
Giles Cope 2019-08-17 12:17:02 +01:00
parent 9dd5c19199
commit 1e02bc62bc
3 changed files with 23 additions and 13 deletions

View File

@ -7,7 +7,7 @@ use rustc::ty::TyCtxt;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::map::Map; use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; 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::struct_span_err;
use syntax_pos::Span; use syntax_pos::Span;
use errors::Applicability; use errors::Applicability;
@ -17,6 +17,7 @@ enum Context {
Normal, Normal,
Loop(hir::LoopSource), Loop(hir::LoopSource),
Closure, Closure,
AsyncClosure,
LabeledBlock, LabeledBlock,
AnonConst, AnonConst,
} }
@ -57,9 +58,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
hir::ExprKind::Loop(ref b, _, source) => { hir::ExprKind::Loop(ref b, _, source) => {
self.with_context(Loop(source), |v| v.visit_block(&b)); 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.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)) => { hir::ExprKind::Block(ref b, Some(_label)) => {
self.with_context(LabeledBlock, |v| v.visit_block(&b)); 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") .span_label(span, "cannot break inside of a closure")
.emit(); .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 => { Normal | AnonConst => {
struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
.span_label(span, "cannot break outside of a loop") .span_label(span, "cannot break outside of a loop")

View File

@ -32,15 +32,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
fn no_break_in_async_block() { fn no_break_in_async_block() {
async { async {
break 0u8; //~ ERROR `break` inside of a closure break 0u8; //~ ERROR `break` inside of an async block
// FIXME: This diagnostic is pretty bad.
}; };
} }
fn no_break_in_async_block_even_with_outer_loop() { fn no_break_in_async_block_even_with_outer_loop() {
loop { loop {
async { async {
break 0u8; //~ ERROR `break` inside of a closure break 0u8; //~ ERROR `break` inside of an async block
}; };
} }
} }

View File

@ -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 --> $DIR/async-block-control-flow-static-semantics.rs:35:9
| |
LL | break 0u8; LL | break 0u8;
| ^^^^^^^^^ cannot break inside of a closure | ^^^^^^^^^ cannot break inside of an async block
error[E0267]: `break` inside of a closure error[E0267]: `break` inside of an async block
--> $DIR/async-block-control-flow-static-semantics.rs:43:13 --> $DIR/async-block-control-flow-static-semantics.rs:42:13
| |
LL | break 0u8; LL | break 0u8;
| ^^^^^^^^^ cannot break inside of a closure | ^^^^^^^^^ cannot break inside of an async block
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:15:43 --> $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 = note: the return type of a function must have a statically known size
error[E0308]: mismatched types 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> { LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
| ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
@ -63,7 +63,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
found type `()` found type `()`
error[E0308]: mismatched types 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> { LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
| ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()