Skip to content

Commit b692d5b

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 b692d5b

19 files changed

+138
-21
lines changed

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, functions, or blocks
166+
.suggestion = use `gen` to make this item a coroutine

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+
}

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
};

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(*fn_sig_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

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
33
|
44
LL | fn main() {
5-
| ---- this is not `async`
5+
| --------- this is not `async`
66
...
77
LL | }.await
88
| ^^^^^ only allowed inside `async` functions and blocks

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -141,39 +141,39 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
141141
--> $DIR/incorrect-syntax-suggestions.rs:68:19
142142
|
143143
LL | fn foo13() -> Result<(), ()> {
144-
| ----- this is not `async`
144+
| ---------------------------- this is not `async`
145145
LL | let _ = bar().await();
146146
| ^^^^^ only allowed inside `async` functions and blocks
147147

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

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

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

172172
error[E0728]: `await` is only allowed inside `async` functions and blocks
173173
--> $DIR/incorrect-syntax-suggestions.rs:87:23
174174
|
175175
LL | fn foo() -> Result<(), ()> {
176-
| --- this is not `async`
176+
| -------------------------- this is not `async`
177177
LL | let _ = bar().await?;
178178
| ^^^^^ only allowed inside `async` functions and blocks
179179

tests/ui/async-await/issues/issue-51751.stderr

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

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-62009-1.rs:6:23
33
|
44
LL | fn main() {
5-
| ---- this is not `async`
5+
| --------- this is not `async`
66
LL | async { let (); }.await;
77
| ^^^^^ only allowed inside `async` functions and blocks
88

99
error[E0728]: `await` is only allowed inside `async` functions and blocks
1010
--> $DIR/issue-62009-1.rs:10:7
1111
|
1212
LL | fn main() {
13-
| ---- this is not `async`
13+
| --------- this is not `async`
1414
...
1515
LL | }.await;
1616
| ^^^^^ only allowed inside `async` functions and blocks
@@ -19,7 +19,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
1919
--> $DIR/issue-62009-1.rs:12:16
2020
|
2121
LL | fn main() {
22-
| ---- this is not `async`
22+
| --------- this is not `async`
2323
...
2424
LL | (|_| 2333).await;
2525
| ^^^^^ only allowed inside `async` functions and blocks

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

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

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

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

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, functions, or blocks
12+
--> $DIR/gen_block.rs:15:16
13+
|
14+
LL | let _ = || yield true;
15+
| ^^^^^^^^^^
16+
|
17+
help: use `gen` to make this item 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`.

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, functions, or blocks
1718
}
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, functions, or blocks
10+
}
11+
12+
gen fn _foo() {
13+
yield;
14+
//~^ ERROR `yield` can only be used in `gen` closures, functions, or blocks
15+
//~| ERROR yield expression outside of coroutine literal
16+
}
+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, functions, or blocks
10+
}
11+
12+
fn _foo() {
13+
yield;
14+
//~^ ERROR `yield` can only be used in `gen` closures, functions, or blocks
15+
//~| ERROR yield expression outside of coroutine literal
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: `yield` can only be used in `gen` closures, functions, or blocks
2+
--> $DIR/missing_gen_in_2024.rs:8:16
3+
|
4+
LL | let _ = || yield;
5+
| ^^^^^
6+
|
7+
help: use `gen` to make this item a coroutine
8+
|
9+
LL | let _ = gen || yield;
10+
| +++
11+
12+
error: `yield` can only be used in `gen` closures, functions, or blocks
13+
--> $DIR/missing_gen_in_2024.rs:13:5
14+
|
15+
LL | yield;
16+
| ^^^^^
17+
|
18+
help: use `gen` to make this item 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`.

tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr

+24-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,19 @@ LL | 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, functions, or blocks
12+
--> $DIR/feature-gate-coroutines.rs:5:5
13+
|
14+
LL | yield true;
15+
| ^^^^^^^^^^
16+
|
17+
help: use `gen` to make this item a coroutine
18+
|
19+
LL | gen fn main() {
20+
| +++
21+
1122
error[E0658]: yield syntax is experimental
12-
--> $DIR/feature-gate-coroutines.rs:9:16
23+
--> $DIR/feature-gate-coroutines.rs:10:16
1324
|
1425
LL | let _ = || yield true;
1526
| ^^^^^^^^^^
@@ -18,13 +29,24 @@ LL | let _ = || yield true;
1829
= help: add `#![feature(coroutines)]` to the crate attributes to enable
1930
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2031

32+
error: `yield` can only be used in `gen` closures, functions, or blocks
33+
--> $DIR/feature-gate-coroutines.rs:10:16
34+
|
35+
LL | let _ = || yield true;
36+
| ^^^^^^^^^^
37+
|
38+
help: use `gen` to make this item a coroutine
39+
|
40+
LL | let _ = gen || yield true;
41+
| +++
42+
2143
error[E0627]: yield expression outside of coroutine literal
2244
--> $DIR/feature-gate-coroutines.rs:5:5
2345
|
2446
LL | yield true;
2547
| ^^^^^^^^^^
2648

27-
error: aborting due to 3 previous errors
49+
error: aborting due to 5 previous errors
2850

2951
Some errors have detailed explanations: E0627, E0658.
3052
For more information about an error, try `rustc --explain E0627`.

tests/ui/feature-gates/feature-gate-coroutines.none.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | yield true;
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

1111
error[E0658]: yield syntax is experimental
12-
--> $DIR/feature-gate-coroutines.rs:9:16
12+
--> $DIR/feature-gate-coroutines.rs:10:16
1313
|
1414
LL | let _ = || yield true;
1515
| ^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | let _ = || yield true;
1919
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020

2121
error[E0658]: yield syntax is experimental
22-
--> $DIR/feature-gate-coroutines.rs:16:5
22+
--> $DIR/feature-gate-coroutines.rs:18:5
2323
|
2424
LL | yield;
2525
| ^^^^^
@@ -29,7 +29,7 @@ LL | yield;
2929
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3030

3131
error[E0658]: yield syntax is experimental
32-
--> $DIR/feature-gate-coroutines.rs:17:5
32+
--> $DIR/feature-gate-coroutines.rs:19:5
3333
|
3434
LL | yield 0;
3535
| ^^^^^^^
@@ -50,7 +50,7 @@ LL | yield true;
5050
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5151

5252
error[E0658]: yield syntax is experimental
53-
--> $DIR/feature-gate-coroutines.rs:9:16
53+
--> $DIR/feature-gate-coroutines.rs:10:16
5454
|
5555
LL | let _ = || yield true;
5656
| ^^^^^^^^^^

tests/ui/feature-gates/feature-gate-coroutines.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ fn main() {
55
yield true; //~ ERROR yield syntax is experimental
66
//~^ ERROR yield expression outside of coroutine literal
77
//[none]~^^ ERROR yield syntax is experimental
8+
//[e2024]~^^^ ERROR `yield` can only be used in `gen` closures, functions, or blocks
89

910
let _ = || yield true; //~ ERROR yield syntax is experimental
1011
//[none]~^ ERROR yield syntax is experimental
12+
//[e2024]~^^ ERROR `yield` can only be used in `gen` closures, functions, or blocks
1113
}
1214

1315
#[cfg(FALSE)]

tests/ui/sanitizer/cfi-coroutine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::async_iter::AsyncIterator;
2727

2828
#[test]
2929
fn general_coroutine() {
30-
let mut coro = |x: i32| {
30+
let mut coro = gen |x: i32| {
3131
yield x;
3232
"done"
3333
};

0 commit comments

Comments
 (0)