Skip to content

Commit 22bc5c5

Browse files
In ConstructCoroutineInClosureShim, pass receiver by ref, not pointer
1 parent 536606b commit 22bc5c5

8 files changed

+81
-21
lines changed

compiler/rustc_mir_transform/src/shim.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1015,8 +1015,8 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
10151015
bug!();
10161016
};
10171017

1018-
// We use `*mut Self` here because we only need to emit an ABI-compatible shim body,
1019-
// rather than match the signature exactly.
1018+
// We use `&mut Self` here because we only need to emit an ABI-compatible shim body,
1019+
// rather than match the signature exactly (which might take `&self` instead).
10201020
//
10211021
// The self type here is a coroutine-closure, not a coroutine, and we never read from
10221022
// it because it never has any captures, because this is only true in the Fn/FnMut
@@ -1025,7 +1025,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
10251025
if receiver_by_ref {
10261026
// Triple-check that there's no captures here.
10271027
assert_eq!(args.as_coroutine_closure().tupled_upvars_ty(), tcx.types.unit);
1028-
self_ty = Ty::new_mut_ptr(tcx, self_ty);
1028+
self_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, self_ty);
10291029
}
10301030

10311031
let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {

compiler/rustc_ty_utils/src/abi.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ fn fn_sig_for_fn_abi<'tcx>(
125125
coroutine_kind = ty::ClosureKind::FnOnce;
126126

127127
// Implementations of `FnMut` and `Fn` for coroutine-closures
128-
// still take their receiver by ref.
129-
if receiver_by_ref { Ty::new_mut_ptr(tcx, coroutine_ty) } else { coroutine_ty }
128+
// still take their receiver by (mut) ref.
129+
if receiver_by_ref {
130+
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
131+
} else {
132+
coroutine_ty
133+
}
130134
} else {
131135
tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region)
132136
};
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DropMe("world") DropMe("hello")
2+
world
3+
hello
+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
}
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

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
22

3-
fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
3+
fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
44
let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10};
55

66
bb0: {

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
22

3-
fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
3+
fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
44
let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10};
55

66
bb0: {

0 commit comments

Comments
 (0)