mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-19 18:34:08 +00:00
Rollup merge of #124777 - veera-sivarajan:bugfix-124495-identify-gen-block, r=compiler-errors
Fix Error Messages for `break` Inside Coroutines Fixes #124495 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`.~~
This commit is contained in:
commit
9b834d01e5
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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 });
|
||||
|
@ -29,14 +29,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
|
||||
|
||||
fn no_break_in_async_block() {
|
||||
async {
|
||||
break 0u8; //~ ERROR `break` inside of an `async` block
|
||||
break 0u8; //~ ERROR `break` inside `async` block
|
||||
};
|
||||
}
|
||||
|
||||
fn no_break_in_async_block_even_with_outer_loop() {
|
||||
loop {
|
||||
async {
|
||||
break 0u8; //~ ERROR `break` inside of an `async` block
|
||||
break 0u8; //~ ERROR `break` inside `async` block
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
error[E0267]: `break` inside of an `async` block
|
||||
error[E0267]: `break` inside `async` block
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:32:9
|
||||
|
|
||||
LL | / async {
|
||||
LL | | break 0u8;
|
||||
| | ^^^^^^^^^ cannot `break` inside of an `async` block
|
||||
| | ^^^^^^^^^ cannot `break` inside `async` block
|
||||
LL | | };
|
||||
| |_____- enclosing `async` block
|
||||
|
||||
error[E0267]: `break` inside of an `async` block
|
||||
error[E0267]: `break` inside `async` block
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:39:13
|
||||
|
|
||||
LL | / async {
|
||||
LL | | break 0u8;
|
||||
| | ^^^^^^^^^ cannot `break` inside of an `async` block
|
||||
| | ^^^^^^^^^ cannot `break` inside `async` block
|
||||
LL | | };
|
||||
| |_________- enclosing `async` block
|
||||
|
||||
|
26
tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
Normal file
26
tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Z unstable-options
|
||||
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(async_closure)]
|
||||
|
||||
async fn async_fn() {
|
||||
break; //~ ERROR `break` inside `async` function
|
||||
}
|
||||
|
||||
gen fn gen_fn() {
|
||||
break; //~ ERROR `break` inside `gen` function
|
||||
}
|
||||
|
||||
async gen fn async_gen_fn() {
|
||||
break; //~ ERROR `break` inside `async gen` function
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = async { break; }; //~ ERROR `break` inside `async` block
|
||||
let _ = async || { break; }; //~ ERROR `break` inside `async` closure
|
||||
|
||||
let _ = gen { break; }; //~ ERROR `break` inside `gen` block
|
||||
|
||||
let _ = async gen { break; }; //~ ERROR `break` inside `async gen` block
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
error[E0267]: `break` inside `async` function
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:8:5
|
||||
|
|
||||
LL | async fn async_fn() {
|
||||
| _____________________-
|
||||
LL | | break;
|
||||
| | ^^^^^ cannot `break` inside `async` function
|
||||
LL | | }
|
||||
| |_- enclosing `async` function
|
||||
|
||||
error[E0267]: `break` inside `gen` function
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:12:5
|
||||
|
|
||||
LL | gen fn gen_fn() {
|
||||
| _________________-
|
||||
LL | | break;
|
||||
| | ^^^^^ cannot `break` inside `gen` function
|
||||
LL | | }
|
||||
| |_- enclosing `gen` function
|
||||
|
||||
error[E0267]: `break` inside `async gen` function
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:16:5
|
||||
|
|
||||
LL | async gen fn async_gen_fn() {
|
||||
| _____________________________-
|
||||
LL | | break;
|
||||
| | ^^^^^ cannot `break` inside `async gen` function
|
||||
LL | | }
|
||||
| |_- enclosing `async gen` function
|
||||
|
||||
error[E0267]: `break` inside `async` block
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:20:21
|
||||
|
|
||||
LL | let _ = async { break; };
|
||||
| --------^^^^^---
|
||||
| | |
|
||||
| | cannot `break` inside `async` block
|
||||
| enclosing `async` block
|
||||
|
||||
error[E0267]: `break` inside `async` closure
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:21:24
|
||||
|
|
||||
LL | let _ = async || { break; };
|
||||
| --^^^^^---
|
||||
| | |
|
||||
| | cannot `break` inside `async` closure
|
||||
| enclosing `async` closure
|
||||
|
||||
error[E0267]: `break` inside `gen` block
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:23:19
|
||||
|
|
||||
LL | let _ = gen { break; };
|
||||
| ------^^^^^---
|
||||
| | |
|
||||
| | cannot `break` inside `gen` block
|
||||
| enclosing `gen` block
|
||||
|
||||
error[E0267]: `break` inside `async gen` block
|
||||
--> $DIR/break-inside-coroutine-issue-124495.rs:25:25
|
||||
|
|
||||
LL | let _ = async gen { break; };
|
||||
| ------------^^^^^---
|
||||
| | |
|
||||
| | cannot `break` inside `async gen` block
|
||||
| enclosing `async gen` block
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0267`.
|
Loading…
Reference in New Issue
Block a user