diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 9d58d301e2b..3deefcaa06c 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -52,16 +52,16 @@ passes_attr_only_in_functions = passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` -passes_break_inside_async_block = - `{$name}` inside of an `async` block - .label = cannot `{$name}` inside of an `async` block - .async_block_label = enclosing `async` block - passes_break_inside_closure = `{$name}` inside of a closure .label = cannot `{$name}` inside of a closure .closure_label = enclosing closure +passes_break_inside_coroutine = + `{$name}` inside `{$kind}` {$source} + .label = cannot `{$name}` inside `{$kind}` {$source} + .coroutine_label = enclosing `{$kind}` {$source} + passes_break_non_loop = `break` with value from a `{$kind}` loop .label = can only break with a value inside `loop` or breakable block diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 65cad82cc8c..b8586e7e974 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1086,14 +1086,16 @@ pub struct BreakInsideClosure<'a> { } #[derive(Diagnostic)] -#[diag(passes_break_inside_async_block, code = E0267)] -pub struct BreakInsideAsyncBlock<'a> { +#[diag(passes_break_inside_coroutine, code = E0267)] +pub struct BreakInsideCoroutine<'a> { #[primary_span] #[label] pub span: Span, - #[label(passes_async_block_label)] - pub closure_span: Span, + #[label(passes_coroutine_label)] + pub coroutine_span: Span, pub name: &'a str, + pub kind: &'a str, + pub source: &'a str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 4b5c4dfe991..3b20112eab7 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -13,7 +13,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::{BytePos, Span}; use crate::errors::{ - BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, + BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, }; @@ -23,7 +23,7 @@ enum Context { Fn, Loop(hir::LoopSource), Closure(Span), - AsyncClosure(Span), + Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource }, UnlabeledBlock(Span), LabeledBlock, Constant, @@ -89,12 +89,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, fn_decl_span, kind, .. }) => { - // FIXME(coroutines): This doesn't handle coroutines correctly let cx = match kind { - hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - )) => AsyncClosure(fn_decl_span), + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(kind, source)) => { + Coroutine { coroutine_span: fn_decl_span, kind, source } + } _ => Closure(fn_decl_span), }; self.visit_fn_decl(fn_decl); @@ -227,8 +225,24 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { Closure(closure_span) => { self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name }); } - AsyncClosure(closure_span) => { - self.sess.dcx().emit_err(BreakInsideAsyncBlock { span, closure_span, name }); + Coroutine { coroutine_span, kind, source } => { + let kind = match kind { + hir::CoroutineDesugaring::Async => "async", + hir::CoroutineDesugaring::Gen => "gen", + hir::CoroutineDesugaring::AsyncGen => "async gen", + }; + let source = match source { + hir::CoroutineSource::Block => "block", + hir::CoroutineSource::Closure => "closure", + hir::CoroutineSource::Fn => "function", + }; + self.sess.dcx().emit_err(BreakInsideCoroutine { + span, + coroutine_span, + name, + kind, + source, + }); } UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => { let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });