Skip to content

Commit df4ba99

Browse files
committed
Auto merge of rust-lang#120712 - compiler-errors:async-closures-harmonize, r=oli-obk
Harmonize `AsyncFn` implementations, make async closures conditionally impl `Fn*` traits This PR implements several changes to the built-in and libcore-provided implementations of `Fn*` and `AsyncFn*` to address two problems: 1. async closures do not implement the `Fn*` family traits, leading to breakage: https://crater-reports.s3.amazonaws.com/pr-120361/index.html 2. *references* to async closures do not implement `AsyncFn*`, as a consequence of the existing blanket impls of the shape `AsyncFn for F where F: Fn, F::Output: Future`. In order to fix (1.), we implement `Fn` traits appropriately for async closures. It turns out that async closures can: * always implement `FnOnce`, meaning that they're drop-in compatible with `FnOnce`-bound combinators like `Option::map`. * conditionally implement `Fn`/`FnMut` if they have no captures, which means that existing usages of async closures should *probably* work without breakage (crater checking this: rust-lang#120712 (comment)). In order to fix (2.), we make all of the built-in callables implement `AsyncFn*` via built-in impls, and instead adjust the blanket impls for `AsyncFn*` provided by libcore to match the blanket impls for `Fn*`.
2 parents f9e40ce + cf1c72f commit df4ba99

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

alloc/src/boxed.rs

+29
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ use core::iter::FusedIterator;
159159
use core::marker::Tuple;
160160
use core::marker::Unsize;
161161
use core::mem::{self, SizedTypeProperties};
162+
use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
162163
use core::ops::{
163164
CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFromDyn, Receiver,
164165
};
@@ -2030,6 +2031,34 @@ impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
20302031
}
20312032
}
20322033

2034+
#[unstable(feature = "async_fn_traits", issue = "none")]
2035+
impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args> for Box<F, A> {
2036+
type Output = F::Output;
2037+
type CallOnceFuture = F::CallOnceFuture;
2038+
2039+
extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture {
2040+
F::async_call_once(*self, args)
2041+
}
2042+
}
2043+
2044+
#[unstable(feature = "async_fn_traits", issue = "none")]
2045+
impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> for Box<F, A> {
2046+
type CallMutFuture<'a> = F::CallMutFuture<'a> where Self: 'a;
2047+
2048+
extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallMutFuture<'_> {
2049+
F::async_call_mut(self, args)
2050+
}
2051+
}
2052+
2053+
#[unstable(feature = "async_fn_traits", issue = "none")]
2054+
impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box<F, A> {
2055+
type CallFuture<'a> = F::CallFuture<'a> where Self: 'a;
2056+
2057+
extern "rust-call" fn async_call(&self, args: Args) -> Self::CallFuture<'_> {
2058+
F::async_call(self, args)
2059+
}
2060+
}
2061+
20332062
#[unstable(feature = "coerce_unsized", issue = "18598")]
20342063
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
20352064

alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
#![feature(array_windows)]
107107
#![feature(ascii_char)]
108108
#![feature(assert_matches)]
109+
#![feature(async_fn_traits)]
109110
#![feature(async_iterator)]
110111
#![feature(coerce_unsized)]
111112
#![feature(const_align_of_val)]

core/src/ops/async_function.rs

+37-14
Original file line numberDiff line numberDiff line change
@@ -65,44 +65,67 @@ pub trait AsyncFnOnce<Args: Tuple> {
6565

6666
mod impls {
6767
use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
68-
use crate::future::Future;
6968
use crate::marker::Tuple;
7069

7170
#[unstable(feature = "async_fn_traits", issue = "none")]
72-
impl<F: Fn<A>, A: Tuple> AsyncFn<A> for F
71+
impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F
7372
where
74-
<F as FnOnce<A>>::Output: Future,
73+
F: AsyncFn<A>,
7574
{
76-
type CallFuture<'a> = <F as FnOnce<A>>::Output where Self: 'a;
75+
type CallFuture<'a> = F::CallFuture<'a> where Self: 'a;
7776

7877
extern "rust-call" fn async_call(&self, args: A) -> Self::CallFuture<'_> {
79-
self.call(args)
78+
F::async_call(*self, args)
8079
}
8180
}
8281

8382
#[unstable(feature = "async_fn_traits", issue = "none")]
84-
impl<F: FnMut<A>, A: Tuple> AsyncFnMut<A> for F
83+
impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F
8584
where
86-
<F as FnOnce<A>>::Output: Future,
85+
F: AsyncFn<A>,
8786
{
88-
type CallMutFuture<'a> = <F as FnOnce<A>>::Output where Self: 'a;
87+
type CallMutFuture<'a> = F::CallFuture<'a> where Self: 'a;
8988

9089
extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallMutFuture<'_> {
91-
self.call_mut(args)
90+
F::async_call(*self, args)
9291
}
9392
}
9493

9594
#[unstable(feature = "async_fn_traits", issue = "none")]
96-
impl<F: FnOnce<A>, A: Tuple> AsyncFnOnce<A> for F
95+
impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F
9796
where
98-
<F as FnOnce<A>>::Output: Future,
97+
F: AsyncFn<A>,
9998
{
100-
type CallOnceFuture = <F as FnOnce<A>>::Output;
99+
type Output = F::Output;
100+
type CallOnceFuture = F::CallFuture<'a>;
101101

102-
type Output = <<F as FnOnce<A>>::Output as Future>::Output;
102+
extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
103+
F::async_call(self, args)
104+
}
105+
}
106+
107+
#[unstable(feature = "async_fn_traits", issue = "none")]
108+
impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F
109+
where
110+
F: AsyncFnMut<A>,
111+
{
112+
type CallMutFuture<'a> = F::CallMutFuture<'a> where Self: 'a;
113+
114+
extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallMutFuture<'_> {
115+
F::async_call_mut(*self, args)
116+
}
117+
}
118+
119+
#[unstable(feature = "async_fn_traits", issue = "none")]
120+
impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F
121+
where
122+
F: AsyncFnMut<A>,
123+
{
124+
type Output = F::Output;
125+
type CallOnceFuture = F::CallMutFuture<'a>;
103126

104127
extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
105-
self.call_once(args)
128+
F::async_call_mut(self, args)
106129
}
107130
}
108131
}

0 commit comments

Comments
 (0)