Skip to content

Commit 5f66961

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 833bbcc commit 5f66961

File tree

3 files changed

+173
-10
lines changed

3 files changed

+173
-10
lines changed

compiler/rustc_passes/messages.ftl

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,55 @@ passes_both_ffi_const_and_pure =
5353
`#[ffi_const]` function cannot be `#[ffi_pure]`
5454
5555
passes_break_inside_async_block =
56-
`{$name}` inside of an `async` block
57-
.label = cannot `{$name}` inside of an `async` block
56+
`{$name}` inside an `async` block
57+
.label = cannot `{$name}` inside an `async` block
5858
.async_block_label = enclosing `async` block
5959
60+
passes_break_inside_async_closure =
61+
`{$name}` inside an `async` closure
62+
.label = cannot `{$name}` inside an `async` closure
63+
.async_closure_label = enclosing `async` closure
64+
65+
passes_break_inside_async_function =
66+
`{$name}` inside an `async` function
67+
.label = cannot `{$name}` inside an `async` function
68+
.async_function_label = enclosing `async` function
69+
70+
passes_break_inside_async_gen_block =
71+
`{$name}` inside an `async gen` block
72+
.label = cannot `{$name}` inside an `async gen` block
73+
.async_gen_block_label = enclosing `async gen` block
74+
75+
passes_break_inside_async_gen_closure =
76+
`{$name}` inside an `async gen` closure
77+
.label = cannot `{$name}` inside an `async gen` closure
78+
.async_gen_closure_label = enclosing `async gen` closure
79+
80+
passes_break_inside_async_gen_function =
81+
`{$name}` inside an `async gen` function
82+
.label = cannot `{$name}` inside an `async gen` function
83+
.async_gen_function_label = enclosing `async gen` function
84+
6085
passes_break_inside_closure =
61-
`{$name}` inside of a closure
62-
.label = cannot `{$name}` inside of a closure
86+
`{$name}` inside a closure
87+
.label = cannot `{$name}` inside a closure
6388
.closure_label = enclosing closure
6489
90+
passes_break_inside_gen_block =
91+
`{$name}` inside a `gen` block
92+
.label = cannot `{$name}` inside a `gen` block
93+
.gen_block_label = enclosing `gen` block
94+
95+
passes_break_inside_gen_closure =
96+
`{$name}` inside a `gen` closure
97+
.label = cannot `{$name}` inside a `gen` closure
98+
.gen_closure_label = enclosing `gen` closure
99+
100+
passes_break_inside_gen_function =
101+
`{$name}` inside a `gen` function
102+
.label = cannot `{$name}` inside a `gen` function
103+
.gen_function_label = enclosing `gen` function
104+
65105
passes_break_non_loop =
66106
`break` with value from a `{$kind}` loop
67107
.label = can only break with a value inside `loop` or breakable block

compiler/rustc_passes/src/errors.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,94 @@ pub struct BreakInsideAsyncBlock<'a> {
10961096
pub name: &'a str,
10971097
}
10981098

1099+
#[derive(Diagnostic)]
1100+
#[diag(passes_break_inside_async_closure, code = E0267)]
1101+
pub struct BreakInsideAsyncClosure<'a> {
1102+
#[primary_span]
1103+
#[label]
1104+
pub span: Span,
1105+
#[label(passes_async_closure_label)]
1106+
pub closure_span: Span,
1107+
pub name: &'a str,
1108+
}
1109+
1110+
#[derive(Diagnostic)]
1111+
#[diag(passes_break_inside_async_function, code = E0267)]
1112+
pub struct BreakInsideAsyncFn<'a> {
1113+
#[primary_span]
1114+
#[label]
1115+
pub span: Span,
1116+
#[label(passes_async_function_label)]
1117+
pub closure_span: Span,
1118+
pub name: &'a str,
1119+
}
1120+
1121+
#[derive(Diagnostic)]
1122+
#[diag(passes_break_inside_gen_block, code = E0267)]
1123+
pub struct BreakInsideGenBlock<'a> {
1124+
#[primary_span]
1125+
#[label]
1126+
pub span: Span,
1127+
#[label(passes_gen_block_label)]
1128+
pub closure_span: Span,
1129+
pub name: &'a str,
1130+
}
1131+
1132+
#[derive(Diagnostic)]
1133+
#[diag(passes_break_inside_gen_function, code = E0267)]
1134+
pub struct BreakInsideGenFn<'a> {
1135+
#[primary_span]
1136+
#[label]
1137+
pub span: Span,
1138+
#[label(passes_gen_function_label)]
1139+
pub closure_span: Span,
1140+
pub name: &'a str,
1141+
}
1142+
1143+
#[derive(Diagnostic)]
1144+
#[diag(passes_break_inside_gen_closure, code = E0267)]
1145+
pub struct BreakInsideGenClosure<'a> {
1146+
#[primary_span]
1147+
#[label]
1148+
pub span: Span,
1149+
#[label(passes_gen_closure_label)]
1150+
pub closure_span: Span,
1151+
pub name: &'a str,
1152+
}
1153+
1154+
#[derive(Diagnostic)]
1155+
#[diag(passes_break_inside_async_gen_block, code = E0267)]
1156+
pub struct BreakInsideAsyncGenBlock<'a> {
1157+
#[primary_span]
1158+
#[label]
1159+
pub span: Span,
1160+
#[label(passes_async_gen_block_label)]
1161+
pub closure_span: Span,
1162+
pub name: &'a str,
1163+
}
1164+
1165+
#[derive(Diagnostic)]
1166+
#[diag(passes_break_inside_async_gen_function, code = E0267)]
1167+
pub struct BreakInsideAsyncGenFn<'a> {
1168+
#[primary_span]
1169+
#[label]
1170+
pub span: Span,
1171+
#[label(passes_async_gen_function_label)]
1172+
pub closure_span: Span,
1173+
pub name: &'a str,
1174+
}
1175+
1176+
#[derive(Diagnostic)]
1177+
#[diag(passes_break_inside_async_gen_closure, code = E0267)]
1178+
pub struct BreakInsideAsyncGenClosure<'a> {
1179+
#[primary_span]
1180+
#[label]
1181+
pub span: Span,
1182+
#[label(passes_async_gen_closure_label)]
1183+
pub closure_span: Span,
1184+
pub name: &'a str,
1185+
}
1186+
10991187
#[derive(Diagnostic)]
11001188
#[diag(passes_outside_loop, code = E0268)]
11011189
pub struct OutsideLoop<'a> {

compiler/rustc_passes/src/loops.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use rustc_span::hygiene::DesugaringKind;
1313
use rustc_span::{BytePos, Span};
1414

1515
use crate::errors::{
16-
BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
16+
BreakInsideAsyncBlock, BreakInsideAsyncClosure, BreakInsideAsyncFn, BreakInsideAsyncGenBlock,
17+
BreakInsideAsyncGenClosure, BreakInsideAsyncGenFn, BreakInsideClosure, BreakInsideGenBlock,
18+
BreakInsideGenClosure, BreakInsideGenFn, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
1719
OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
1820
};
1921

@@ -23,7 +25,9 @@ enum Context {
2325
Fn,
2426
Loop(hir::LoopSource),
2527
Closure(Span),
26-
AsyncClosure(Span),
28+
Async(Span, hir::CoroutineSource),
29+
Gen(Span, hir::CoroutineSource),
30+
AsyncGen(Span, hir::CoroutineSource),
2731
UnlabeledBlock(Span),
2832
LabeledBlock,
2933
Constant,
@@ -89,12 +93,19 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
8993
hir::ExprKind::Closure(&hir::Closure {
9094
ref fn_decl, body, fn_decl_span, kind, ..
9195
}) => {
92-
// FIXME(coroutines): This doesn't handle coroutines correctly
9396
let cx = match kind {
9497
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
9598
hir::CoroutineDesugaring::Async,
96-
hir::CoroutineSource::Block,
97-
)) => AsyncClosure(fn_decl_span),
99+
kind,
100+
)) => Async(fn_decl_span, kind),
101+
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
102+
hir::CoroutineDesugaring::Gen,
103+
kind,
104+
)) => Gen(fn_decl_span, kind),
105+
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
106+
hir::CoroutineDesugaring::AsyncGen,
107+
kind,
108+
)) => AsyncGen(fn_decl_span, kind),
98109
_ => Closure(fn_decl_span),
99110
};
100111
self.visit_fn_decl(fn_decl);
@@ -227,9 +238,33 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
227238
Closure(closure_span) => {
228239
self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name });
229240
}
230-
AsyncClosure(closure_span) => {
241+
Async(closure_span, hir::CoroutineSource::Block) => {
231242
self.sess.dcx().emit_err(BreakInsideAsyncBlock { span, closure_span, name });
232243
}
244+
Async(closure_span, hir::CoroutineSource::Closure) => {
245+
self.sess.dcx().emit_err(BreakInsideAsyncClosure { span, closure_span, name });
246+
}
247+
Async(closure_span, hir::CoroutineSource::Fn) => {
248+
self.sess.dcx().emit_err(BreakInsideAsyncFn { span, closure_span, name });
249+
}
250+
Gen(closure_span, hir::CoroutineSource::Block) => {
251+
self.sess.dcx().emit_err(BreakInsideGenBlock { span, closure_span, name });
252+
}
253+
Gen(closure_span, hir::CoroutineSource::Fn) => {
254+
self.sess.dcx().emit_err(BreakInsideGenFn { span, closure_span, name });
255+
}
256+
Gen(closure_span, hir::CoroutineSource::Closure) => {
257+
self.sess.dcx().emit_err(BreakInsideGenClosure { span, closure_span, name });
258+
}
259+
AsyncGen(closure_span, hir::CoroutineSource::Block) => {
260+
self.sess.dcx().emit_err(BreakInsideAsyncGenBlock { span, closure_span, name });
261+
}
262+
AsyncGen(closure_span, hir::CoroutineSource::Fn) => {
263+
self.sess.dcx().emit_err(BreakInsideAsyncGenFn { span, closure_span, name });
264+
}
265+
AsyncGen(closure_span, hir::CoroutineSource::Closure) => {
266+
self.sess.dcx().emit_err(BreakInsideAsyncGenClosure { span, closure_span, name });
267+
}
233268
UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
234269
let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });
235270
self.sess.dcx().emit_err(OutsideLoop { span, name, is_break, suggestion });

0 commit comments

Comments
 (0)