Skip to content

Commit 86b2568

Browse files
committed
Auto merge of #123792 - oli-obk:coroutine_closures, r=compiler-errors
Require explicitly marking closures as coroutines instead of relying on patching up the closure to be a coroutine if it happens to contain a `yield` expression. I only do this in the 2024 edition, as the `gen` keyword is only available there.
2 parents 9f08266 + e84df5b commit 86b2568

File tree

4 files changed

+25
-25
lines changed

4 files changed

+25
-25
lines changed

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;

tests/pass/coroutine.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
3-
#![feature(coroutines, coroutine_trait, never_type)]
3+
#![feature(coroutines, coroutine_trait, never_type, stmt_expr_attributes)]
44

55
use std::fmt::Debug;
66
use std::mem::ManuallyDrop;
@@ -43,9 +43,9 @@ fn basic() {
4343
panic!()
4444
}
4545

46-
finish(1, false, || yield 1);
46+
finish(1, false, #[coroutine] || yield 1);
4747

48-
finish(3, false, || {
48+
finish(3, false, #[coroutine] || {
4949
let mut x = 0;
5050
yield 1;
5151
x += 1;
@@ -55,27 +55,27 @@ fn basic() {
5555
assert_eq!(x, 2);
5656
});
5757

58-
finish(7 * 8 / 2, false, || {
58+
finish(7 * 8 / 2, false, #[coroutine] || {
5959
for i in 0..8 {
6060
yield i;
6161
}
6262
});
6363

64-
finish(1, false, || {
64+
finish(1, false, #[coroutine] || {
6565
if true {
6666
yield 1;
6767
} else {
6868
}
6969
});
7070

71-
finish(1, false, || {
71+
finish(1, false, #[coroutine] || {
7272
if false {
7373
} else {
7474
yield 1;
7575
}
7676
});
7777

78-
finish(2, false, || {
78+
finish(2, false, #[coroutine] || {
7979
if {
8080
yield 1;
8181
false
@@ -88,7 +88,7 @@ fn basic() {
8888

8989
// also test self-referential coroutines
9090
assert_eq!(
91-
finish(5, true, static || {
91+
finish(5, true, #[coroutine] static || {
9292
let mut x = 5;
9393
let y = &mut x;
9494
*y = 5;
@@ -99,7 +99,7 @@ fn basic() {
9999
10
100100
);
101101
assert_eq!(
102-
finish(5, true, || {
102+
finish(5, true, #[coroutine] || {
103103
let mut x = Box::new(5);
104104
let y = &mut *x;
105105
*y = 5;
@@ -111,7 +111,7 @@ fn basic() {
111111
);
112112

113113
let b = true;
114-
finish(1, false, || {
114+
finish(1, false, #[coroutine] || {
115115
yield 1;
116116
if b {
117117
return;
@@ -123,7 +123,7 @@ fn basic() {
123123
drop(x);
124124
});
125125

126-
finish(3, false, || {
126+
finish(3, false, #[coroutine] || {
127127
yield 1;
128128
#[allow(unreachable_code)]
129129
let _x: (String, !) = (String::new(), {
@@ -172,7 +172,7 @@ fn smoke_resume_arg() {
172172
}
173173

174174
drain(
175-
&mut |mut b| {
175+
&mut #[coroutine] |mut b| {
176176
while b != 0 {
177177
b = yield (b + 1);
178178
}
@@ -181,21 +181,21 @@ fn smoke_resume_arg() {
181181
vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))],
182182
);
183183

184-
expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))]));
184+
expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))]));
185185

186186
expect_drops(6, || {
187187
drain(
188-
&mut |a| yield yield a,
188+
&mut #[coroutine] |a| yield yield a,
189189
vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))],
190190
)
191191
});
192192

193193
#[allow(unreachable_code)]
194-
expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))]));
194+
expect_drops(2, || drain(&mut #[coroutine] |a| yield return a, vec![(DropMe, Complete(DropMe))]));
195195

196196
expect_drops(2, || {
197197
drain(
198-
&mut |a: DropMe| {
198+
&mut #[coroutine] |a: DropMe| {
199199
if false { yield () } else { a }
200200
},
201201
vec![(DropMe, Complete(DropMe))],
@@ -205,7 +205,7 @@ fn smoke_resume_arg() {
205205
expect_drops(4, || {
206206
drain(
207207
#[allow(unused_assignments, unused_variables)]
208-
&mut |mut a: DropMe| {
208+
&mut #[coroutine] |mut a: DropMe| {
209209
a = yield;
210210
a = yield;
211211
a = yield;
@@ -228,7 +228,7 @@ fn uninit_fields() {
228228
}
229229

230230
fn run<T>(x: bool, y: bool) {
231-
let mut c = || {
231+
let mut c = #[coroutine] || {
232232
if x {
233233
let _a: T;
234234
if y {

tests/pass/stacked-borrows/coroutine-self-referential.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
22
// this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
3-
#![feature(coroutines, coroutine_trait)]
3+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
44

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

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

tests/pass/track-caller-attribute.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ fn test_coroutine() {
232232
}
233233

234234
#[rustfmt::skip]
235-
let coroutine = #[track_caller] |arg: String| {
235+
let coroutine = #[track_caller] #[coroutine] |arg: String| {
236236
yield ("first", arg.clone(), Location::caller());
237237
yield ("second", arg.clone(), Location::caller());
238238
};
@@ -255,15 +255,15 @@ fn test_coroutine() {
255255
assert_eq!(mono_loc.column(), 42);
256256

257257
#[rustfmt::skip]
258-
let non_tracked_coroutine = || { yield Location::caller(); };
258+
let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); };
259259
let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
260260
let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
261261
CoroutineState::Yielded(val) => val,
262262
_ => unreachable!(),
263263
};
264264
assert_eq!(non_tracked_loc.file(), file!());
265265
assert_eq!(non_tracked_loc.line(), non_tracked_line);
266-
assert_eq!(non_tracked_loc.column(), 44);
266+
assert_eq!(non_tracked_loc.column(), 57);
267267
}
268268

269269
fn main() {

0 commit comments

Comments
 (0)