Skip to content

Commit dfb5b89

Browse files
authored
Rollup merge of #123049 - compiler-errors:coroutine-closure-rcvr, r=oli-obk
In `ConstructCoroutineInClosureShim`, pass receiver by mut ref, not mut pointer The receivers were compatible at codegen time, but did not necessarily have the same layouts due to niches, which was caught by miri. Fixes #3400 r? oli-obk
2 parents 860b63e + 4bf56fa commit dfb5b89

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

tests/pass/async-closure-drop.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#![feature(async_closure, noop_waker, async_fn_traits)]
2+
3+
use std::future::Future;
4+
use std::pin::pin;
5+
use std::task::*;
6+
7+
pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
8+
let mut fut = pin!(fut);
9+
let ctx = &mut Context::from_waker(Waker::noop());
10+
11+
loop {
12+
match fut.as_mut().poll(ctx) {
13+
Poll::Pending => {}
14+
Poll::Ready(t) => break t,
15+
}
16+
}
17+
}
18+
19+
async fn call_once(f: impl async FnOnce(DropMe)) {
20+
f(DropMe("world")).await;
21+
}
22+
23+
#[derive(Debug)]
24+
struct DropMe(&'static str);
25+
26+
impl Drop for DropMe {
27+
fn drop(&mut self) {
28+
println!("{}", self.0);
29+
}
30+
}
31+
32+
pub fn main() {
33+
block_on(async {
34+
let b = DropMe("hello");
35+
let async_closure = async move |a: DropMe| {
36+
println!("{a:?} {b:?}");
37+
};
38+
call_once(async_closure).await;
39+
});
40+
}

tests/pass/async-closure-drop.stdout

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DropMe("world") DropMe("hello")
2+
world
3+
hello

tests/pass/async-closure.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(async_closure, noop_waker, async_fn_traits)]
22

33
use std::future::Future;
4+
use std::ops::{AsyncFnMut, AsyncFnOnce};
45
use std::pin::pin;
56
use std::task::*;
67

@@ -16,25 +17,36 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
1617
}
1718
}
1819

19-
async fn call_once(f: impl async FnOnce(DropMe)) {
20-
f(DropMe("world")).await;
20+
async fn call_mut(f: &mut impl AsyncFnMut(i32)) {
21+
f(0).await;
2122
}
2223

23-
#[derive(Debug)]
24-
struct DropMe(&'static str);
24+
async fn call_once(f: impl AsyncFnOnce(i32)) {
25+
f(1).await;
26+
}
2527

26-
impl Drop for DropMe {
27-
fn drop(&mut self) {
28-
println!("{}", self.0);
29-
}
28+
async fn call_normal<F: Future<Output = ()>>(f: &impl Fn(i32) -> F) {
29+
f(0).await;
30+
}
31+
32+
async fn call_normal_once<F: Future<Output = ()>>(f: impl FnOnce(i32) -> F) {
33+
f(1).await;
3034
}
3135

3236
pub fn main() {
3337
block_on(async {
34-
let b = DropMe("hello");
35-
let async_closure = async move |a: DropMe| {
36-
println!("{a:?} {b:?}");
38+
let b = 2i32;
39+
let mut async_closure = async move |a: i32| {
40+
println!("{a} {b}");
3741
};
42+
call_mut(&mut async_closure).await;
3843
call_once(async_closure).await;
44+
45+
// No-capture closures implement `Fn`.
46+
let async_closure = async move |a: i32| {
47+
println!("{a}");
48+
};
49+
call_normal(&async_closure).await;
50+
call_normal_once(async_closure).await;
3951
});
4052
}

tests/pass/async-closure.stdout

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
DropMe("world") DropMe("hello")
2-
world
3-
hello
1+
0 2
2+
1 2
3+
0
4+
1

0 commit comments

Comments
 (0)