Skip to content

Commit

Permalink
Error on using yield without also using gen on the closure
Browse files Browse the repository at this point in the history
And suggest adding the `gen` to the closure or function
  • Loading branch information
oli-obk committed Apr 11, 2024
1 parent e8a6ccc commit f0906f5
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 62 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,6 @@ ast_lowering_underscore_expr_lhs_assign =
.label = `_` not allowed here
ast_lowering_use_angle_brackets = use angle brackets instead
ast_lowering_yield_in_closure =
`yield` can only be used in `gen` closures or blocks
.suggestion = use `gen` to make the closure a coroutine
9 changes: 9 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,12 @@ pub(crate) struct AsyncBoundOnlyForFnTraits {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_lowering_yield_in_closure)]
pub(crate) struct YieldInClosure {
#[primary_span]
pub span: Span,
#[suggestion(code = "gen ", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Option<Span>,
}
6 changes: 6 additions & 0 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use super::errors::{
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
use crate::errors::YieldInClosure;
use crate::{FnDeclKind, ImplTraitPosition};
use rustc_ast::ptr::P as AstP;
use rustc_ast::*;
Expand Down Expand Up @@ -1578,7 +1579,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
.emit();
}
if self.tcx.sess.edition().at_least_rust_2024() {
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
self.dcx().emit_err(YieldInClosure { span, suggestion });
}
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));

false
}
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body,
..
}) => {
self.with_new_scopes(ident.span, |this| {
self.with_new_scopes(span, |this| {
// Note: we don't need to change the return type from `T` to
// `impl Future<Output = T>` here because lower_body
// only cares about the input argument patterns in the function
Expand Down
14 changes: 9 additions & 5 deletions tests/ui/async-await/async-outside-of-await-issue-121096.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
|
LL | fn main() {
| ---- this is not `async`
...
LL | }.await
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | async {
LL | | use std::ops::Add;
LL | | let _ = 1.add(3);
LL | | }.await
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | }
| |_- this is not `async`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,42 +140,54 @@ LL | }
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:68:19
|
LL | fn foo13() -> Result<(), ()> {
| ----- this is not `async`
LL | let _ = bar().await();
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn foo13() -> Result<(), ()> {
LL | | let _ = bar().await();
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | Ok(())
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:73:19
|
LL | fn foo14() -> Result<(), ()> {
| ----- this is not `async`
LL | let _ = bar().await()?;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn foo14() -> Result<(), ()> {
LL | | let _ = bar().await()?;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | Ok(())
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:78:19
|
LL | fn foo15() -> Result<(), ()> {
| ----- this is not `async`
LL | let _ = bar().await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn foo15() -> Result<(), ()> {
LL | | let _ = bar().await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | | Ok(())
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:82:19
|
LL | fn foo16() -> Result<(), ()> {
| ----- this is not `async`
LL | let _ = bar().await?;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn foo16() -> Result<(), ()> {
LL | | let _ = bar().await?;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | | Ok(())
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:87:23
|
LL | fn foo() -> Result<(), ()> {
| --- this is not `async`
LL | let _ = bar().await?;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn foo() -> Result<(), ()> {
LL | | let _ = bar().await?;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | | Ok(())
LL | | }
| |_____- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/incorrect-syntax-suggestions.rs:94:23
Expand Down
12 changes: 7 additions & 5 deletions tests/ui/async-await/issues/issue-51751.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-51751.rs:9:27
|
LL | fn main() {
| ---- this is not `async`
LL | let result = inc(10000);
LL | let finished = result.await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | let result = inc(10000);
LL | | let finished = result.await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | }
| |_- this is not `async`

error: aborting due to 1 previous error

Expand Down
44 changes: 30 additions & 14 deletions tests/ui/async-await/issues/issue-62009-1.stderr
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009-1.rs:6:23
|
LL | fn main() {
| ---- this is not `async`
LL | async { let (); }.await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | async { let (); }.await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | async {
... |
LL | |
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009-1.rs:10:7
|
LL | fn main() {
| ---- this is not `async`
...
LL | }.await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | async { let (); }.await;
LL | |
LL | | async {
LL | | let task1 = print_dur().await;
LL | | }.await;
| | ^^^^^ only allowed inside `async` functions and blocks
... |
LL | |
LL | | }
| |_- this is not `async`

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009-1.rs:12:16
|
LL | fn main() {
| ---- this is not `async`
...
LL | (|_| 2333).await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | async { let (); }.await;
LL | |
LL | | async {
... |
LL | | (|_| 2333).await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | }
| |_- this is not `async`

error: aborting due to 3 previous errors

Expand Down
10 changes: 6 additions & 4 deletions tests/ui/async-await/issues/issue-62009-2.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009-2.rs:8:23
|
LL | fn main() {
| ---- this is not `async`
LL | (async || 2333)().await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | (async || 2333)().await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | }
| |_- this is not `async`

error: aborting due to 1 previous error

Expand Down
12 changes: 7 additions & 5 deletions tests/ui/async-await/issues/non-async-enclosing-span.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/non-async-enclosing-span.rs:9:28
|
LL | fn main() {
| ---- this is not `async`
LL | let x = move || {};
LL | let y = do_the_thing().await;
| ^^^^^ only allowed inside `async` functions and blocks
LL | / fn main() {
LL | | let x = move || {};
LL | | let y = do_the_thing().await;
| | ^^^^^ only allowed inside `async` functions and blocks
LL | |
LL | | }
| |_- this is not `async`

error: aborting due to 1 previous error

Expand Down
13 changes: 12 additions & 1 deletion tests/ui/coroutine/gen_block.e2024.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ LL | let _ = || yield true;
= help: add `#![feature(coroutines)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: `yield` can only be used in `gen` closures or blocks
--> $DIR/gen_block.rs:15:16
|
LL | let _ = || yield true;
| ^^^^^^^^^^
|
help: use `gen` to make the closure a coroutine
|
LL | let _ = gen || yield true;
| +++

error[E0282]: type annotations needed
--> $DIR/gen_block.rs:6:13
|
LL | let x = gen {};
| ^^^^^^ cannot infer type

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0282, E0658.
For more information about an error, try `rustc --explain E0282`.
1 change: 1 addition & 0 deletions tests/ui/coroutine/gen_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ fn main() {

let _ = || yield true; //[none]~ ERROR yield syntax is experimental
//~^ ERROR yield syntax is experimental
//[e2024]~^^ ERROR `yield` can only be used in `gen` closures or blocks
}
16 changes: 16 additions & 0 deletions tests/ui/coroutine/missing_gen_in_2024.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ edition: 2024
//@ compile-flags: -Zunstable-options
//@ run-rustfix

#![feature(coroutines, gen_blocks)]

fn main() {
let _ = gen || yield;
//~^ ERROR `yield` can only be used in `gen` closures or blocks
}

gen fn _foo() {
yield;
//~^ ERROR `yield` can only be used in `gen` closures or blocks
//~| ERROR yield expression outside of coroutine literal
}
16 changes: 16 additions & 0 deletions tests/ui/coroutine/missing_gen_in_2024.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ edition: 2024
//@ compile-flags: -Zunstable-options
//@ run-rustfix

#![feature(coroutines, gen_blocks)]

fn main() {
let _ = || yield;
//~^ ERROR `yield` can only be used in `gen` closures or blocks
}

fn _foo() {
yield;
//~^ ERROR `yield` can only be used in `gen` closures or blocks
//~| ERROR yield expression outside of coroutine literal
}
31 changes: 31 additions & 0 deletions tests/ui/coroutine/missing_gen_in_2024.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
error: `yield` can only be used in `gen` closures or blocks
--> $DIR/missing_gen_in_2024.rs:8:16
|
LL | let _ = || yield;
| ^^^^^
|
help: use `gen` to make the closure a coroutine
|
LL | let _ = gen || yield;
| +++

error: `yield` can only be used in `gen` closures or blocks
--> $DIR/missing_gen_in_2024.rs:13:5
|
LL | yield;
| ^^^^^
|
help: use `gen` to make the closure a coroutine
|
LL | gen fn _foo() {
| +++

error[E0627]: yield expression outside of coroutine literal
--> $DIR/missing_gen_in_2024.rs:13:5
|
LL | yield;
| ^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0627`.
Loading

0 comments on commit f0906f5

Please sign in to comment.