Skip to content

Commit 0e6f7c6

Browse files
Add AsyncFn family of traits
1 parent 71696e5 commit 0e6f7c6

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@
227227
#![feature(fundamental)]
228228
#![feature(generic_arg_infer)]
229229
#![feature(if_let_guard)]
230+
#![feature(impl_trait_in_assoc_type)]
230231
#![feature(inline_const)]
231232
#![feature(intra_doc_pointers)]
232233
#![feature(intrinsics)]
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use crate::future::Future;
2+
use crate::marker::Tuple;
3+
4+
/// An async-aware version of the [`Fn`](crate::ops::Fn) trait.
5+
///
6+
/// All `async fn` and functions returning futures implement this trait.
7+
#[unstable(feature = "async_fn_traits", issue = "none")]
8+
#[rustc_paren_sugar]
9+
#[fundamental]
10+
#[must_use = "async closures are lazy and do nothing unless called"]
11+
pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
12+
/// Future returned by [`AsyncFn::async_call`].
13+
#[unstable(feature = "async_fn_traits", issue = "none")]
14+
type CallFuture<'a>: Future<Output = Self::Output>
15+
where
16+
Self: 'a;
17+
18+
/// Call the [`AsyncFn`], returning a future which may borrow from the called closure.
19+
#[unstable(feature = "async_fn_traits", issue = "none")]
20+
extern "rust-call" fn async_call(&self, args: Args) -> Self::CallFuture<'_>;
21+
}
22+
23+
/// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait.
24+
///
25+
/// All `async fn` and functions returning futures implement this trait.
26+
#[unstable(feature = "async_fn_traits", issue = "none")]
27+
#[rustc_paren_sugar]
28+
#[fundamental]
29+
#[must_use = "async closures are lazy and do nothing unless called"]
30+
pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
31+
/// Future returned by [`AsyncFnMut::async_call_mut`].
32+
#[unstable(feature = "async_fn_traits", issue = "none")]
33+
type CallMutFuture<'a>: Future<Output = Self::Output>
34+
where
35+
Self: 'a;
36+
37+
/// Call the [`AsyncFnMut`], returning a future which may borrow from the called closure.
38+
#[unstable(feature = "async_fn_traits", issue = "none")]
39+
extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallMutFuture<'_>;
40+
}
41+
42+
/// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait.
43+
///
44+
/// All `async fn` and functions returning futures implement this trait.
45+
#[unstable(feature = "async_fn_traits", issue = "none")]
46+
#[rustc_paren_sugar]
47+
#[fundamental]
48+
#[must_use = "async closures are lazy and do nothing unless called"]
49+
pub trait AsyncFnOnce<Args: Tuple> {
50+
/// Future returned by [`AsyncFnOnce::async_call_once`].
51+
#[unstable(feature = "async_fn_traits", issue = "none")]
52+
type CallOnceFuture: Future<Output = Self::Output>;
53+
54+
/// Output type of the called closure's future.
55+
#[unstable(feature = "async_fn_traits", issue = "none")]
56+
type Output;
57+
58+
/// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.
59+
#[unstable(feature = "async_fn_traits", issue = "none")]
60+
extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture;
61+
}
62+
63+
mod impls {
64+
use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
65+
use crate::future::Future;
66+
use crate::marker::Tuple;
67+
68+
#[unstable(feature = "async_fn_traits", issue = "none")]
69+
impl<F: Fn<A>, A: Tuple> AsyncFn<A> for F
70+
where
71+
<F as FnOnce<A>>::Output: Future,
72+
{
73+
type CallFuture<'a> = impl Future<Output = Self::Output> where Self: 'a;
74+
75+
extern "rust-call" fn async_call(&self, args: A) -> Self::CallFuture<'_> {
76+
async { self.call(args).await }
77+
}
78+
}
79+
80+
#[unstable(feature = "async_fn_traits", issue = "none")]
81+
impl<F: FnMut<A>, A: Tuple> AsyncFnMut<A> for F
82+
where
83+
<F as FnOnce<A>>::Output: Future,
84+
{
85+
type CallMutFuture<'a> = impl Future<Output = Self::Output> where Self: 'a;
86+
87+
extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallMutFuture<'_> {
88+
async { self.call_mut(args).await }
89+
}
90+
}
91+
92+
#[unstable(feature = "async_fn_traits", issue = "none")]
93+
impl<F: FnOnce<A>, A: Tuple> AsyncFnOnce<A> for F
94+
where
95+
<F as FnOnce<A>>::Output: Future,
96+
{
97+
type CallOnceFuture = impl Future<Output = Self::Output>;
98+
99+
type Output = <<F as FnOnce<A>>::Output as Future>::Output;
100+
101+
extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
102+
async { self.call_once(args).await }
103+
}
104+
}
105+
}

library/core/src/ops/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
#![stable(feature = "rust1", since = "1.0.0")]
140140

141141
mod arith;
142+
mod async_function;
142143
mod bit;
143144
mod control_flow;
144145
mod coroutine;
@@ -173,6 +174,9 @@ pub use self::drop::Drop;
173174
#[stable(feature = "rust1", since = "1.0.0")]
174175
pub use self::function::{Fn, FnMut, FnOnce};
175176

177+
#[unstable(feature = "async_fn_traits", issue = "none")]
178+
pub use self::async_function::{AsyncFn, AsyncFnMut, AsyncFnOnce};
179+
176180
#[stable(feature = "rust1", since = "1.0.0")]
177181
pub use self::index::{Index, IndexMut};
178182

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition: 2021
2+
// check-pass
3+
4+
#![feature(async_fn_traits)]
5+
6+
use std::ops::AsyncFn;
7+
8+
async fn foo() {}
9+
10+
async fn call_asyncly(f: impl AsyncFn(i32) -> i32) -> i32 {
11+
f.async_call((1i32,)).await
12+
}
13+
14+
fn main() {
15+
let fut = call_asyncly(|x| async move { x + 1 });
16+
}

tests/ui/did_you_mean/bad-assoc-ty.stderr

+8-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,14 @@ error[E0223]: ambiguous associated type
191191
--> $DIR/bad-assoc-ty.rs:33:10
192192
|
193193
LL | type H = Fn(u8) -> (u8)::Output;
194-
| ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output`
194+
| ^^^^^^^^^^^^^^^^^^^^^^
195+
|
196+
help: use fully-qualified syntax
197+
|
198+
LL | type H = <(dyn Fn(u8) -> u8 + 'static) as AsyncFnOnce>::Output;
199+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200+
LL | type H = <(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output;
201+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195202

196203
error[E0223]: ambiguous associated type
197204
--> $DIR/bad-assoc-ty.rs:39:19

0 commit comments

Comments
 (0)