Skip to content

Commit f0906f5

Browse files
committed
Error on using yield without also using gen on the closure
And suggest adding the `gen` to the closure or function
1 parent e8a6ccc commit f0906f5

19 files changed

+217
-62
lines changed

Diff for: compiler/rustc_ast_lowering/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,6 @@ ast_lowering_underscore_expr_lhs_assign =
161161
.label = `_` not allowed here
162162
163163
ast_lowering_use_angle_brackets = use angle brackets instead
164+
ast_lowering_yield_in_closure =
165+
`yield` can only be used in `gen` closures or blocks
166+
.suggestion = use `gen` to make the closure a coroutine

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

+9
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,12 @@ pub(crate) struct AsyncBoundOnlyForFnTraits {
414414
#[primary_span]
415415
pub span: Span,
416416
}
417+
418+
#[derive(Diagnostic)]
419+
#[diag(ast_lowering_yield_in_closure)]
420+
pub(crate) struct YieldInClosure {
421+
#[primary_span]
422+
pub span: Span,
423+
#[suggestion(code = "gen ", applicability = "maybe-incorrect", style = "verbose")]
424+
pub suggestion: Option<Span>,
425+
}

Diff for: compiler/rustc_ast_lowering/src/expr.rs

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::errors::{
88
};
99
use super::ResolverAstLoweringExt;
1010
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
11+
use crate::errors::YieldInClosure;
1112
use crate::{FnDeclKind, ImplTraitPosition};
1213
use rustc_ast::ptr::P as AstP;
1314
use rustc_ast::*;
@@ -1578,7 +1579,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
15781579
)
15791580
.emit();
15801581
}
1582+
if self.tcx.sess.edition().at_least_rust_2024() {
1583+
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
1584+
self.dcx().emit_err(YieldInClosure { span, suggestion });
1585+
}
15811586
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
1587+
15821588
false
15831589
}
15841590
};

Diff for: compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
203203
body,
204204
..
205205
}) => {
206-
self.with_new_scopes(ident.span, |this| {
206+
self.with_new_scopes(span, |this| {
207207
// Note: we don't need to change the return type from `T` to
208208
// `impl Future<Output = T>` here because lower_body
209209
// only cares about the input argument patterns in the function

Diff for: tests/ui/async-await/async-outside-of-await-issue-121096.stderr

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
33
|
4-
LL | fn main() {
5-
| ---- this is not `async`
6-
...
7-
LL | }.await
8-
| ^^^^^ only allowed inside `async` functions and blocks
4+
LL | / fn main() {
5+
LL | | async {
6+
LL | | use std::ops::Add;
7+
LL | | let _ = 1.add(3);
8+
LL | | }.await
9+
| | ^^^^^ only allowed inside `async` functions and blocks
10+
LL | |
11+
LL | | }
12+
| |_- this is not `async`
913

1014
error: aborting due to 1 previous error
1115

Diff for: tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr

+32-20
Original file line numberDiff line numberDiff line change
@@ -140,42 +140,54 @@ LL | }
140140
error[E0728]: `await` is only allowed inside `async` functions and blocks
141141
--> $DIR/incorrect-syntax-suggestions.rs:68:19
142142
|
143-
LL | fn foo13() -> Result<(), ()> {
144-
| ----- this is not `async`
145-
LL | let _ = bar().await();
146-
| ^^^^^ only allowed inside `async` functions and blocks
143+
LL | / fn foo13() -> Result<(), ()> {
144+
LL | | let _ = bar().await();
145+
| | ^^^^^ only allowed inside `async` functions and blocks
146+
LL | |
147+
LL | | Ok(())
148+
LL | | }
149+
| |_- this is not `async`
147150

148151
error[E0728]: `await` is only allowed inside `async` functions and blocks
149152
--> $DIR/incorrect-syntax-suggestions.rs:73:19
150153
|
151-
LL | fn foo14() -> Result<(), ()> {
152-
| ----- this is not `async`
153-
LL | let _ = bar().await()?;
154-
| ^^^^^ only allowed inside `async` functions and blocks
154+
LL | / fn foo14() -> Result<(), ()> {
155+
LL | | let _ = bar().await()?;
156+
| | ^^^^^ only allowed inside `async` functions and blocks
157+
LL | |
158+
LL | | Ok(())
159+
LL | | }
160+
| |_- this is not `async`
155161

156162
error[E0728]: `await` is only allowed inside `async` functions and blocks
157163
--> $DIR/incorrect-syntax-suggestions.rs:78:19
158164
|
159-
LL | fn foo15() -> Result<(), ()> {
160-
| ----- this is not `async`
161-
LL | let _ = bar().await;
162-
| ^^^^^ only allowed inside `async` functions and blocks
165+
LL | / fn foo15() -> Result<(), ()> {
166+
LL | | let _ = bar().await;
167+
| | ^^^^^ only allowed inside `async` functions and blocks
168+
LL | | Ok(())
169+
LL | | }
170+
| |_- this is not `async`
163171

164172
error[E0728]: `await` is only allowed inside `async` functions and blocks
165173
--> $DIR/incorrect-syntax-suggestions.rs:82:19
166174
|
167-
LL | fn foo16() -> Result<(), ()> {
168-
| ----- this is not `async`
169-
LL | let _ = bar().await?;
170-
| ^^^^^ only allowed inside `async` functions and blocks
175+
LL | / fn foo16() -> Result<(), ()> {
176+
LL | | let _ = bar().await?;
177+
| | ^^^^^ only allowed inside `async` functions and blocks
178+
LL | | Ok(())
179+
LL | | }
180+
| |_- this is not `async`
171181

172182
error[E0728]: `await` is only allowed inside `async` functions and blocks
173183
--> $DIR/incorrect-syntax-suggestions.rs:87:23
174184
|
175-
LL | fn foo() -> Result<(), ()> {
176-
| --- this is not `async`
177-
LL | let _ = bar().await?;
178-
| ^^^^^ only allowed inside `async` functions and blocks
185+
LL | / fn foo() -> Result<(), ()> {
186+
LL | | let _ = bar().await?;
187+
| | ^^^^^ only allowed inside `async` functions and blocks
188+
LL | | Ok(())
189+
LL | | }
190+
| |_____- this is not `async`
179191

180192
error[E0728]: `await` is only allowed inside `async` functions and blocks
181193
--> $DIR/incorrect-syntax-suggestions.rs:94:23

Diff for: tests/ui/async-await/issues/issue-51751.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-51751.rs:9:27
33
|
4-
LL | fn main() {
5-
| ---- this is not `async`
6-
LL | let result = inc(10000);
7-
LL | let finished = result.await;
8-
| ^^^^^ only allowed inside `async` functions and blocks
4+
LL | / fn main() {
5+
LL | | let result = inc(10000);
6+
LL | | let finished = result.await;
7+
| | ^^^^^ only allowed inside `async` functions and blocks
8+
LL | |
9+
LL | | }
10+
| |_- this is not `async`
911

1012
error: aborting due to 1 previous error
1113

Diff for: tests/ui/async-await/issues/issue-62009-1.stderr

+30-14
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,44 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-62009-1.rs:6:23
33
|
4-
LL | fn main() {
5-
| ---- this is not `async`
6-
LL | async { let (); }.await;
7-
| ^^^^^ only allowed inside `async` functions and blocks
4+
LL | / fn main() {
5+
LL | | async { let (); }.await;
6+
| | ^^^^^ only allowed inside `async` functions and blocks
7+
LL | |
8+
LL | | async {
9+
... |
10+
LL | |
11+
LL | | }
12+
| |_- this is not `async`
813

914
error[E0728]: `await` is only allowed inside `async` functions and blocks
1015
--> $DIR/issue-62009-1.rs:10:7
1116
|
12-
LL | fn main() {
13-
| ---- this is not `async`
14-
...
15-
LL | }.await;
16-
| ^^^^^ only allowed inside `async` functions and blocks
17+
LL | / fn main() {
18+
LL | | async { let (); }.await;
19+
LL | |
20+
LL | | async {
21+
LL | | let task1 = print_dur().await;
22+
LL | | }.await;
23+
| | ^^^^^ only allowed inside `async` functions and blocks
24+
... |
25+
LL | |
26+
LL | | }
27+
| |_- this is not `async`
1728

1829
error[E0728]: `await` is only allowed inside `async` functions and blocks
1930
--> $DIR/issue-62009-1.rs:12:16
2031
|
21-
LL | fn main() {
22-
| ---- this is not `async`
23-
...
24-
LL | (|_| 2333).await;
25-
| ^^^^^ only allowed inside `async` functions and blocks
32+
LL | / fn main() {
33+
LL | | async { let (); }.await;
34+
LL | |
35+
LL | | async {
36+
... |
37+
LL | | (|_| 2333).await;
38+
| | ^^^^^ only allowed inside `async` functions and blocks
39+
LL | |
40+
LL | | }
41+
| |_- this is not `async`
2642

2743
error: aborting due to 3 previous errors
2844

Diff for: tests/ui/async-await/issues/issue-62009-2.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-62009-2.rs:8:23
33
|
4-
LL | fn main() {
5-
| ---- this is not `async`
6-
LL | (async || 2333)().await;
7-
| ^^^^^ only allowed inside `async` functions and blocks
4+
LL | / fn main() {
5+
LL | | (async || 2333)().await;
6+
| | ^^^^^ only allowed inside `async` functions and blocks
7+
LL | |
8+
LL | | }
9+
| |_- this is not `async`
810

911
error: aborting due to 1 previous error
1012

Diff for: tests/ui/async-await/issues/non-async-enclosing-span.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/non-async-enclosing-span.rs:9:28
33
|
4-
LL | fn main() {
5-
| ---- this is not `async`
6-
LL | let x = move || {};
7-
LL | let y = do_the_thing().await;
8-
| ^^^^^ only allowed inside `async` functions and blocks
4+
LL | / fn main() {
5+
LL | | let x = move || {};
6+
LL | | let y = do_the_thing().await;
7+
| | ^^^^^ only allowed inside `async` functions and blocks
8+
LL | |
9+
LL | | }
10+
| |_- this is not `async`
911

1012
error: aborting due to 1 previous error
1113

Diff for: tests/ui/coroutine/gen_block.e2024.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,24 @@ LL | let _ = || yield true;
88
= help: add `#![feature(coroutines)]` to the crate attributes to enable
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

11+
error: `yield` can only be used in `gen` closures or blocks
12+
--> $DIR/gen_block.rs:15:16
13+
|
14+
LL | let _ = || yield true;
15+
| ^^^^^^^^^^
16+
|
17+
help: use `gen` to make the closure a coroutine
18+
|
19+
LL | let _ = gen || yield true;
20+
| +++
21+
1122
error[E0282]: type annotations needed
1223
--> $DIR/gen_block.rs:6:13
1324
|
1425
LL | let x = gen {};
1526
| ^^^^^^ cannot infer type
1627

17-
error: aborting due to 2 previous errors
28+
error: aborting due to 3 previous errors
1829

1930
Some errors have detailed explanations: E0282, E0658.
2031
For more information about an error, try `rustc --explain E0282`.

Diff for: tests/ui/coroutine/gen_block.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ fn main() {
1414

1515
let _ = || yield true; //[none]~ ERROR yield syntax is experimental
1616
//~^ ERROR yield syntax is experimental
17+
//[e2024]~^^ ERROR `yield` can only be used in `gen` closures or blocks
1718
}

Diff for: tests/ui/coroutine/missing_gen_in_2024.fixed

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
//@ run-rustfix
4+
5+
#![feature(coroutines, gen_blocks)]
6+
7+
fn main() {
8+
let _ = gen || yield;
9+
//~^ ERROR `yield` can only be used in `gen` closures or blocks
10+
}
11+
12+
gen fn _foo() {
13+
yield;
14+
//~^ ERROR `yield` can only be used in `gen` closures or blocks
15+
//~| ERROR yield expression outside of coroutine literal
16+
}

Diff for: tests/ui/coroutine/missing_gen_in_2024.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
//@ run-rustfix
4+
5+
#![feature(coroutines, gen_blocks)]
6+
7+
fn main() {
8+
let _ = || yield;
9+
//~^ ERROR `yield` can only be used in `gen` closures or blocks
10+
}
11+
12+
fn _foo() {
13+
yield;
14+
//~^ ERROR `yield` can only be used in `gen` closures or blocks
15+
//~| ERROR yield expression outside of coroutine literal
16+
}

Diff for: tests/ui/coroutine/missing_gen_in_2024.stderr

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: `yield` can only be used in `gen` closures or blocks
2+
--> $DIR/missing_gen_in_2024.rs:8:16
3+
|
4+
LL | let _ = || yield;
5+
| ^^^^^
6+
|
7+
help: use `gen` to make the closure a coroutine
8+
|
9+
LL | let _ = gen || yield;
10+
| +++
11+
12+
error: `yield` can only be used in `gen` closures or blocks
13+
--> $DIR/missing_gen_in_2024.rs:13:5
14+
|
15+
LL | yield;
16+
| ^^^^^
17+
|
18+
help: use `gen` to make the closure a coroutine
19+
|
20+
LL | gen fn _foo() {
21+
| +++
22+
23+
error[E0627]: yield expression outside of coroutine literal
24+
--> $DIR/missing_gen_in_2024.rs:13:5
25+
|
26+
LL | yield;
27+
| ^^^^^
28+
29+
error: aborting due to 3 previous errors
30+
31+
For more information about this error, try `rustc --explain E0627`.

0 commit comments

Comments
 (0)