Skip to content

Commit d8ab6bf

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

File tree

265 files changed

+1184
-790
lines changed

Some content is hidden

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

265 files changed

+1184
-790
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 `#[coroutine]` closures, or `gen` blocks
166+
.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
@@ -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 = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
424+
pub suggestion: Option<Span>,
425+
}

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::*;
@@ -979,6 +980,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
979980
None
980981
};
981982
let body_id = this.lower_fn_body(decl, |this| {
983+
this.coroutine_kind = coroutine_kind;
982984
let e = this.lower_expr_mut(body);
983985
coroutine_kind = this.coroutine_kind;
984986
e
@@ -1577,7 +1579,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
15771579
)
15781580
.emit();
15791581
}
1582+
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
1583+
self.dcx().emit_err(YieldInClosure { span, suggestion });
15801584
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
1585+
15811586
false
15821587
}
15831588
};

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,
@@ -122,9 +123,12 @@ fn main() {
122123
test_simd();
123124
}
124125

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

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_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(generic_nonzero)]
3940
#![feature(if_let_guard)]
4041
#![feature(inline_const)]

compiler/rustc_middle/src/ty/context.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -1262,20 +1262,23 @@ impl<'tcx> TyCtxt<'tcx> {
12621262
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
12631263

12641264
let definitions = &self.untracked.definitions;
1265-
std::iter::from_coroutine(|| {
1266-
let mut i = 0;
1267-
1268-
// Recompute the number of definitions each time, because our caller may be creating
1269-
// new ones.
1270-
while i < { definitions.read().num_definitions() } {
1271-
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
1272-
yield LocalDefId { local_def_index };
1273-
i += 1;
1274-
}
1265+
std::iter::from_coroutine(
1266+
#[cfg_attr(not(bootstrap), coroutine)]
1267+
|| {
1268+
let mut i = 0;
1269+
1270+
// Recompute the number of definitions each time, because our caller may be creating
1271+
// new ones.
1272+
while i < { definitions.read().num_definitions() } {
1273+
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
1274+
yield LocalDefId { local_def_index };
1275+
i += 1;
1276+
}
12751277

1276-
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
1277-
definitions.freeze();
1278-
})
1278+
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
1279+
definitions.freeze();
1280+
},
1281+
)
12791282
}
12801283

12811284
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
22

3-
#![feature(coroutines, coroutine_trait)]
3+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
44

55
fn main() {
6-
let _ = || {
6+
let _ = #[coroutine] || {
77
yield;
88
};
99
}

src/tools/clippy/tests/ui/large_futures.fixed

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(coroutines)]
21
#![warn(clippy::large_futures)]
32
#![allow(clippy::never_loop)]
43
#![allow(clippy::future_not_send)]

src/tools/clippy/tests/ui/large_futures.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(coroutines)]
21
#![warn(clippy::large_futures)]
32
#![allow(clippy::never_loop)]
43
#![allow(clippy::future_not_send)]

src/tools/clippy/tests/ui/large_futures.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: large future with a size of 16385 bytes
2-
--> tests/ui/large_futures.rs:11:9
2+
--> tests/ui/large_futures.rs:10:9
33
|
44
LL | big_fut([0u8; 1024 * 16]).await;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
@@ -8,37 +8,37 @@ LL | big_fut([0u8; 1024 * 16]).await;
88
= help: to override `-D warnings` add `#[allow(clippy::large_futures)]`
99

1010
error: large future with a size of 16386 bytes
11-
--> tests/ui/large_futures.rs:15:5
11+
--> tests/ui/large_futures.rs:14:5
1212
|
1313
LL | f.await
1414
| ^ help: consider `Box::pin` on it: `Box::pin(f)`
1515

1616
error: large future with a size of 16387 bytes
17-
--> tests/ui/large_futures.rs:20:9
17+
--> tests/ui/large_futures.rs:19:9
1818
|
1919
LL | wait().await;
2020
| ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
2121

2222
error: large future with a size of 16387 bytes
23-
--> tests/ui/large_futures.rs:25:13
23+
--> tests/ui/large_futures.rs:24:13
2424
|
2525
LL | wait().await;
2626
| ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
2727

2828
error: large future with a size of 65540 bytes
29-
--> tests/ui/large_futures.rs:33:5
29+
--> tests/ui/large_futures.rs:32:5
3030
|
3131
LL | foo().await;
3232
| ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
3333

3434
error: large future with a size of 49159 bytes
35-
--> tests/ui/large_futures.rs:35:5
35+
--> tests/ui/large_futures.rs:34:5
3636
|
3737
LL | calls_fut(fut).await;
3838
| ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
3939

4040
error: large future with a size of 65540 bytes
41-
--> tests/ui/large_futures.rs:48:5
41+
--> tests/ui/large_futures.rs:47:5
4242
|
4343
LL | / async {
4444
LL | |
@@ -59,7 +59,7 @@ LL + })
5959
|
6060

6161
error: large future with a size of 65540 bytes
62-
--> tests/ui/large_futures.rs:60:13
62+
--> tests/ui/large_futures.rs:59:13
6363
|
6464
LL | / async {
6565
LL | | let x = [0i32; 1024 * 16];

src/tools/clippy/tests/ui/redundant_locals.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@aux-build:proc_macros.rs
22
#![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
33
#![warn(clippy::redundant_locals)]
4-
#![feature(async_closure, coroutines)]
4+
#![feature(async_closure, coroutines, stmt_expr_attributes)]
55

66
extern crate proc_macros;
77
use proc_macros::{external, with_span};
@@ -191,11 +191,11 @@ fn issue12225() {
191191
let v4 = v4;
192192
dbg!(&v4);
193193
});
194-
assert_static(static || {
194+
assert_static(#[coroutine] static || {
195195
let v5 = v5;
196196
yield;
197197
});
198-
assert_static(|| {
198+
assert_static(#[coroutine] || {
199199
let v6 = v6;
200200
yield;
201201
});

src/tools/miri/tests/fail/coroutine-pinned-moved.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2-
#![feature(coroutines, coroutine_trait)]
2+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
33

44
use std::{
55
ops::{Coroutine, CoroutineState},
66
pin::Pin,
77
};
88

99
fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
10-
static move || {
10+
#[coroutine] static move || {
1111
let mut num = 0;
1212
let num = &mut num;
1313
*num += 0;

0 commit comments

Comments
 (0)