core/ops/
async_function.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use crate::future::Future;
use crate::marker::Tuple;

/// An async-aware version of the [`Fn`](crate::ops::Fn) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
#[lang = "async_fn"]
pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
    /// Call the [`AsyncFn`], returning a future which may borrow from the called closure.
    #[unstable(feature = "async_fn_traits", issue = "none")]
    extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_>;
}

/// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
#[lang = "async_fn_mut"]
pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
    /// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
    #[unstable(feature = "async_fn_traits", issue = "none")]
    #[lang = "call_ref_future"]
    type CallRefFuture<'a>: Future<Output = Self::Output>
    where
        Self: 'a;

    /// Call the [`AsyncFnMut`], returning a future which may borrow from the called closure.
    #[unstable(feature = "async_fn_traits", issue = "none")]
    extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_>;
}

/// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
#[lang = "async_fn_once"]
pub trait AsyncFnOnce<Args: Tuple> {
    /// Future returned by [`AsyncFnOnce::async_call_once`].
    #[unstable(feature = "async_fn_traits", issue = "none")]
    #[lang = "call_once_future"]
    type CallOnceFuture: Future<Output = Self::Output>;

    /// Output type of the called closure's future.
    #[unstable(feature = "async_fn_traits", issue = "none")]
    #[lang = "async_fn_once_output"]
    type Output;

    /// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.
    #[unstable(feature = "async_fn_traits", issue = "none")]
    extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture;
}

mod impls {
    use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
    use crate::marker::Tuple;

    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
    impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F
    where
        F: AsyncFn<A>,
    {
        extern "rust-call" fn async_call(&self, args: A) -> Self::CallRefFuture<'_> {
            F::async_call(*self, args)
        }
    }

    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
    impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F
    where
        F: AsyncFn<A>,
    {
        type CallRefFuture<'a>
            = F::CallRefFuture<'a>
        where
            Self: 'a;

        extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallRefFuture<'_> {
            F::async_call(*self, args)
        }
    }

    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
    impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F
    where
        F: AsyncFn<A>,
    {
        type Output = F::Output;
        type CallOnceFuture = F::CallRefFuture<'a>;

        extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
            F::async_call(self, args)
        }
    }

    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
    impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F
    where
        F: AsyncFnMut<A>,
    {
        type CallRefFuture<'a>
            = F::CallRefFuture<'a>
        where
            Self: 'a;

        extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallRefFuture<'_> {
            F::async_call_mut(*self, args)
        }
    }

    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
    impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F
    where
        F: AsyncFnMut<A>,
    {
        type Output = F::Output;
        type CallOnceFuture = F::CallRefFuture<'a>;

        extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
            F::async_call_mut(self, args)
        }
    }
}

mod internal_implementation_detail {
    /// A helper trait that is used to enforce that the `ClosureKind` of a goal
    /// is within the capabilities of a `CoroutineClosure`, and which allows us
    /// to delay the projection of the tupled upvar types until after upvar
    /// analysis is complete.
    ///
    /// The `Self` type is expected to be the `kind_ty` of the coroutine-closure,
    /// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind`
    /// for an explanation of that). The `GoalKind` is also the same type, but
    /// representing the kind of the trait that the closure is being called with.
    #[lang = "async_fn_kind_helper"]
    trait AsyncFnKindHelper<GoalKind> {
        // Projects a set of closure inputs (arguments), a region, and a set of upvars
        // (by move and by ref) to the upvars that we expect the coroutine to have
        // according to the `GoalKind` parameter above.
        //
        // The `Upvars` parameter should be the upvars of the parent coroutine-closure,
        // and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape
        // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
        // of the closure's self-capture, and these upvar types will be instantiated with
        // the `'closure_env` region provided to the associated type.
        #[lang = "async_fn_kind_upvars"]
        type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
    }
}