Skip to content

Commit aef0f40

Browse files
committed
Error on using yield without also using #[coroutine] on the closure
And suggest adding the `#[coroutine]` to the closure
1 parent a589632 commit aef0f40

File tree

279 files changed

+1293
-889
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

279 files changed

+1293
-889
lines changed

compiler/rustc_ast_lowering/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign =
163163
.label = `_` not allowed here
164164
165165
ast_lowering_use_angle_brackets = use angle brackets instead
166+
ast_lowering_yield_in_closure =
167+
`yield` can only be used in `#[coroutine]` closures, or `gen` blocks
168+
.suggestion = use `#[coroutine]` to make this closure a coroutine

compiler/rustc_ast_lowering/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
421421
#[primary_span]
422422
pub span: Span,
423423
}
424+
425+
#[derive(Diagnostic)]
426+
#[diag(ast_lowering_yield_in_closure)]
427+
pub(crate) struct YieldInClosure {
428+
#[primary_span]
429+
pub span: Span,
430+
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
431+
pub suggestion: Option<Span>,
432+
}

compiler/rustc_ast_lowering/src/expr.rs

+5
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::*;
@@ -977,6 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
977978
None
978979
};
979980
let body_id = this.lower_fn_body(decl, |this| {
981+
this.coroutine_kind = coroutine_kind;
980982
let e = this.lower_expr_mut(body);
981983
coroutine_kind = this.coroutine_kind;
982984
e
@@ -1575,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
15751577
)
15761578
.emit();
15771579
}
1580+
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
1581+
self.dcx().emit_err(YieldInClosure { span, suggestion });
15781582
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
1583+
15791584
false
15801585
}
15811586
};

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

compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(coroutines, coroutine_trait)]
1+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
22

33
use std::ops::Coroutine;
44
use std::pin::Pin;
@@ -8,7 +8,8 @@ fn main() {
88
}
99

1010
fn run_coroutine<T>() {
11-
let mut coroutine = || {
11+
let mut coroutine = #[coroutine]
12+
|| {
1213
yield;
1314
return;
1415
};

compiler/rustc_codegen_cranelift/example/std_example.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(
22
core_intrinsics,
33
coroutines,
4+
stmt_expr_attributes,
45
coroutine_trait,
56
is_sorted,
67
repr_simd,
@@ -123,9 +124,12 @@ fn main() {
123124
test_simd();
124125
}
125126

126-
Box::pin(move |mut _task_context| {
127-
yield ();
128-
})
127+
Box::pin(
128+
#[coroutine]
129+
move |mut _task_context| {
130+
yield ();
131+
},
132+
)
129133
.as_mut()
130134
.resume(0);
131135

compiler/rustc_codegen_gcc/example/std_example.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![allow(internal_features)]
2-
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
2+
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
33

44
#[cfg(feature="master")]
55
#[cfg(target_arch="x86_64")]
@@ -103,7 +103,7 @@ fn main() {
103103
test_simd();
104104
}
105105

106-
Box::pin(move |mut _task_context| {
106+
Box::pin(#[coroutine] move |mut _task_context| {
107107
yield ();
108108
}).as_mut().resume(0);
109109

compiler/rustc_error_codes/src/error_codes/E0626.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ yield point.
44
Erroneous code example:
55

66
```compile_fail,E0626
7-
# #![feature(coroutines, coroutine_trait, pin)]
7+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
88
# use std::ops::Coroutine;
99
# use std::pin::Pin;
10-
let mut b = || {
10+
let mut b = #[coroutine] || {
1111
let a = &String::new(); // <-- This borrow...
1212
yield (); // ...is still in scope here, when the yield occurs.
1313
println!("{}", a);
@@ -23,10 +23,10 @@ resolve the previous example by removing the borrow and just storing
2323
the integer by value:
2424

2525
```
26-
# #![feature(coroutines, coroutine_trait, pin)]
26+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
2727
# use std::ops::Coroutine;
2828
# use std::pin::Pin;
29-
let mut b = || {
29+
let mut b = #[coroutine] || {
3030
let a = 3;
3131
yield ();
3232
println!("{}", a);
@@ -41,10 +41,10 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
4141
This error also frequently arises with iteration:
4242

4343
```compile_fail,E0626
44-
# #![feature(coroutines, coroutine_trait, pin)]
44+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
4545
# use std::ops::Coroutine;
4646
# use std::pin::Pin;
47-
let mut b = || {
47+
let mut b = #[coroutine] || {
4848
let v = vec![1,2,3];
4949
for &x in &v { // <-- borrow of `v` is still in scope...
5050
yield x; // ...when this yield occurs.
@@ -57,10 +57,10 @@ Such cases can sometimes be resolved by iterating "by value" (or using
5757
`into_iter()`) to avoid borrowing:
5858

5959
```
60-
# #![feature(coroutines, coroutine_trait, pin)]
60+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
6161
# use std::ops::Coroutine;
6262
# use std::pin::Pin;
63-
let mut b = || {
63+
let mut b = #[coroutine] || {
6464
let v = vec![1,2,3];
6565
for x in v { // <-- Take ownership of the values instead!
6666
yield x; // <-- Now yield is OK.
@@ -72,10 +72,10 @@ Pin::new(&mut b).resume(());
7272
If taking ownership is not an option, using indices can work too:
7373

7474
```
75-
# #![feature(coroutines, coroutine_trait, pin)]
75+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
7676
# use std::ops::Coroutine;
7777
# use std::pin::Pin;
78-
let mut b = || {
78+
let mut b = #[coroutine] || {
7979
let v = vec![1,2,3];
8080
let len = v.len(); // (*)
8181
for i in 0..len {

compiler/rustc_error_codes/src/error_codes/E0627.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ A yield expression was used outside of the coroutine literal.
33
Erroneous code example:
44

55
```compile_fail,E0627
6-
#![feature(coroutines, coroutine_trait)]
6+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
77
88
fn fake_coroutine() -> &'static str {
99
yield 1;
@@ -19,10 +19,10 @@ The error occurs because keyword `yield` can only be used inside the coroutine
1919
literal. This can be fixed by constructing the coroutine correctly.
2020

2121
```
22-
#![feature(coroutines, coroutine_trait)]
22+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
2323
2424
fn main() {
25-
let mut coroutine = || {
25+
let mut coroutine = #[coroutine] || {
2626
yield 1;
2727
return "foo"
2828
};

compiler/rustc_error_codes/src/error_codes/E0628.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ More than one parameter was used for a coroutine.
33
Erroneous code example:
44

55
```compile_fail,E0628
6-
#![feature(coroutines, coroutine_trait)]
6+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
77
88
fn main() {
9-
let coroutine = |a: i32, b: i32| {
9+
let coroutine = #[coroutine] |a: i32, b: i32| {
1010
// error: too many parameters for a coroutine
1111
// Allowed only 0 or 1 parameter
1212
yield a;
@@ -20,10 +20,10 @@ at most 1 parameter for the coroutine. For example, we might resolve
2020
the previous example by passing only one parameter.
2121

2222
```
23-
#![feature(coroutines, coroutine_trait)]
23+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
2424
2525
fn main() {
26-
let coroutine = |a: i32| {
26+
let coroutine = #[coroutine] |a: i32| {
2727
yield a;
2828
};
2929
}

compiler/rustc_error_codes/src/error_codes/E0727.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ A `yield` clause was used in an `async` context.
33
Erroneous code example:
44

55
```compile_fail,E0727,edition2018
6-
#![feature(coroutines)]
6+
#![feature(coroutines, stmt_expr_attributes)]
77
88
fn main() {
9-
let coroutine = || {
9+
let coroutine = #[coroutine] || {
1010
async {
1111
yield;
1212
}
@@ -20,10 +20,10 @@ which is not yet supported.
2020
To fix this error, you have to move `yield` out of the `async` block:
2121

2222
```edition2018
23-
#![feature(coroutines)]
23+
#![feature(coroutines, stmt_expr_attributes)]
2424
2525
fn main() {
26-
let coroutine = || {
26+
let coroutine = #[coroutine] || {
2727
yield;
2828
};
2929
}

compiler/rustc_metadata/src/rmeta/decoder.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -1260,30 +1260,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
12601260
id: DefIndex,
12611261
sess: &'a Session,
12621262
) -> impl Iterator<Item = ModChild> + 'a {
1263-
iter::from_coroutine(move || {
1264-
if let Some(data) = &self.root.proc_macro_data {
1265-
// If we are loading as a proc macro, we want to return
1266-
// the view of this crate as a proc macro crate.
1267-
if id == CRATE_DEF_INDEX {
1268-
for child_index in data.macros.decode(self) {
1263+
iter::from_coroutine(
1264+
#[cfg_attr(not(bootstrap), coroutine)]
1265+
move || {
1266+
if let Some(data) = &self.root.proc_macro_data {
1267+
// If we are loading as a proc macro, we want to return
1268+
// the view of this crate as a proc macro crate.
1269+
if id == CRATE_DEF_INDEX {
1270+
for child_index in data.macros.decode(self) {
1271+
yield self.get_mod_child(child_index, sess);
1272+
}
1273+
}
1274+
} else {
1275+
// Iterate over all children.
1276+
let non_reexports =
1277+
self.root.tables.module_children_non_reexports.get(self, id);
1278+
for child_index in non_reexports.unwrap().decode(self) {
12691279
yield self.get_mod_child(child_index, sess);
12701280
}
1271-
}
1272-
} else {
1273-
// Iterate over all children.
1274-
let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
1275-
for child_index in non_reexports.unwrap().decode(self) {
1276-
yield self.get_mod_child(child_index, sess);
1277-
}
12781281

1279-
let reexports = self.root.tables.module_children_reexports.get(self, id);
1280-
if !reexports.is_default() {
1281-
for reexport in reexports.decode((self, sess)) {
1282-
yield reexport;
1282+
let reexports = self.root.tables.module_children_reexports.get(self, id);
1283+
if !reexports.is_default() {
1284+
for reexport in reexports.decode((self, sess)) {
1285+
yield reexport;
1286+
}
12831287
}
12841288
}
1285-
}
1286-
})
1289+
},
1290+
)
12871291
}
12881292

12891293
fn is_ctfe_mir_available(self, id: DefIndex) -> bool {

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![feature(const_type_name)]
3636
#![feature(discriminant_kind)]
3737
#![feature(coroutines)]
38+
#![feature(stmt_expr_attributes)]
3839
#![feature(if_let_guard)]
3940
#![feature(inline_const)]
4041
#![feature(iter_from_coroutine)]

0 commit comments

Comments
 (0)