Auto merge of #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: https://github.com/rust-lang/rust/pull/120712#issuecomment-1930587805). 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*`.
This commit is contained in:
commit
757b8efed4
21 changed files with 706 additions and 263 deletions
|
@ -159,6 +159,7 @@ use core::iter::FusedIterator;
|
|||
use core::marker::Tuple;
|
||||
use core::marker::Unsize;
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
|
||||
use core::ops::{
|
||||
CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFromDyn, Receiver,
|
||||
};
|
||||
|
@ -2030,6 +2031,34 @@ impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||
impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args> for Box<F, A> {
|
||||
type Output = F::Output;
|
||||
type CallOnceFuture = F::CallOnceFuture;
|
||||
|
||||
extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture {
|
||||
F::async_call_once(*self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||
impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> for Box<F, A> {
|
||||
type CallMutFuture<'a> = F::CallMutFuture<'a> where Self: 'a;
|
||||
|
||||
extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallMutFuture<'_> {
|
||||
F::async_call_mut(self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||
impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box<F, A> {
|
||||
type CallFuture<'a> = F::CallFuture<'a> where Self: 'a;
|
||||
|
||||
extern "rust-call" fn async_call(&self, args: Args) -> Self::CallFuture<'_> {
|
||||
F::async_call(self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
#![feature(array_windows)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(async_fn_traits)]
|
||||
#![feature(async_iterator)]
|
||||
#![feature(coerce_unsized)]
|
||||
#![feature(const_align_of_val)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue