Skip to content

Commit 21ccec0

Browse files
Fix Error Messages for break Inside Coroutines
Previously, `break` inside `gen` blocks and functions were incorrectly identified to be enclosed by a closure. This PR fixes it by displaying an appropriate error message for async blocks, async closures, async functions, gen blocks, gen closures, gen functions, async gen blocks, async gen closures and async gen functions. Note: gen closure and async gen closure are not supported by the compiler yet but I have added an error message here assuming that they might be implemented in the future. Also, fixes grammar in a few places by replacing `inside of a $coroutine` with `inside a $coroutine`.
1 parent 4271383 commit 21ccec0

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

Diff for: compiler/rustc_passes/messages.ftl

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ passes_attr_only_in_functions =
5252
passes_both_ffi_const_and_pure =
5353
`#[ffi_const]` function cannot be `#[ffi_pure]`
5454
55-
passes_break_inside_async_block =
56-
`{$name}` inside of an `async` block
57-
.label = cannot `{$name}` inside of an `async` block
58-
.async_block_label = enclosing `async` block
59-
6055
passes_break_inside_closure =
6156
`{$name}` inside of a closure
6257
.label = cannot `{$name}` inside of a closure
6358
.closure_label = enclosing closure
6459
60+
passes_break_inside_coroutine =
61+
`{$name}` inside `{$kind}` {$source}
62+
.label = cannot `{$name}` inside `{$kind}` {$source}
63+
.coroutine_label = enclosing `{$kind}` {$source}
64+
6565
passes_break_non_loop =
6666
`break` with value from a `{$kind}` loop
6767
.label = can only break with a value inside `loop` or breakable block

Diff for: compiler/rustc_passes/src/errors.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1086,14 +1086,16 @@ pub struct BreakInsideClosure<'a> {
10861086
}
10871087

10881088
#[derive(Diagnostic)]
1089-
#[diag(passes_break_inside_async_block, code = E0267)]
1090-
pub struct BreakInsideAsyncBlock<'a> {
1089+
#[diag(passes_break_inside_coroutine, code = E0267)]
1090+
pub struct BreakInsideCoroutine<'a> {
10911091
#[primary_span]
10921092
#[label]
10931093
pub span: Span,
1094-
#[label(passes_async_block_label)]
1095-
pub closure_span: Span,
1094+
#[label(passes_coroutine_label)]
1095+
pub coroutine_span: Span,
10961096
pub name: &'a str,
1097+
pub kind: &'a str,
1098+
pub source: &'a str,
10971099
}
10981100

10991101
#[derive(Diagnostic)]

Diff for: compiler/rustc_passes/src/loops.rs

+23-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_span::hygiene::DesugaringKind;
1313
use rustc_span::{BytePos, Span};
1414

1515
use crate::errors::{
16-
BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
16+
BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
1717
OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
1818
};
1919

@@ -23,7 +23,7 @@ enum Context {
2323
Fn,
2424
Loop(hir::LoopSource),
2525
Closure(Span),
26-
AsyncClosure(Span),
26+
Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource },
2727
UnlabeledBlock(Span),
2828
LabeledBlock,
2929
Constant,
@@ -89,12 +89,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
8989
hir::ExprKind::Closure(&hir::Closure {
9090
ref fn_decl, body, fn_decl_span, kind, ..
9191
}) => {
92-
// FIXME(coroutines): This doesn't handle coroutines correctly
9392
let cx = match kind {
94-
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
95-
hir::CoroutineDesugaring::Async,
96-
hir::CoroutineSource::Block,
97-
)) => AsyncClosure(fn_decl_span),
93+
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(kind, source)) => {
94+
Coroutine { coroutine_span: fn_decl_span, kind, source }
95+
}
9896
_ => Closure(fn_decl_span),
9997
};
10098
self.visit_fn_decl(fn_decl);
@@ -227,8 +225,24 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
227225
Closure(closure_span) => {
228226
self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name });
229227
}
230-
AsyncClosure(closure_span) => {
231-
self.sess.dcx().emit_err(BreakInsideAsyncBlock { span, closure_span, name });
228+
Coroutine { coroutine_span, kind, source } => {
229+
let kind = match kind {
230+
hir::CoroutineDesugaring::Async => "async",
231+
hir::CoroutineDesugaring::Gen => "gen",
232+
hir::CoroutineDesugaring::AsyncGen => "async gen",
233+
};
234+
let source = match source {
235+
hir::CoroutineSource::Block => "block",
236+
hir::CoroutineSource::Closure => "closure",
237+
hir::CoroutineSource::Fn => "function",
238+
};
239+
self.sess.dcx().emit_err(BreakInsideCoroutine {
240+
span,
241+
coroutine_span,
242+
name,
243+
kind,
244+
source,
245+
});
232246
}
233247
UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
234248
let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });

0 commit comments

Comments
 (0)