]>
Commit | Line | Data |
---|---|---|
48663c56 | 1 | #![stable(feature = "futures_api", since = "1.36.0")] |
83c7162d | 2 | |
5e7ed085 FG |
3 | //! Asynchronous basic functionality. |
4 | //! | |
5 | //! Please see the fundamental [`async`] and [`await`] keywords and the [async book] | |
6 | //! for more information on asynchronous programming in Rust. | |
7 | //! | |
8 | //! [`async`]: ../../std/keyword.async.html | |
9 | //! [`await`]: ../../std/keyword.await.html | |
10 | //! [async book]: https://rust-lang.github.io/async-book/ | |
2c00a5a8 | 11 | |
ba9703b0 XL |
12 | use crate::{ |
13 | ops::{Generator, GeneratorState}, | |
14 | pin::Pin, | |
15 | ptr::NonNull, | |
16 | task::{Context, Poll}, | |
17 | }; | |
18 | ||
8faf50e0 | 19 | mod future; |
f9f354fc | 20 | mod into_future; |
a2a8927a | 21 | mod join; |
f9f354fc | 22 | mod pending; |
f035d41b | 23 | mod poll_fn; |
f9f354fc XL |
24 | mod ready; |
25 | ||
48663c56 | 26 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 27 | pub use self::future::Future; |
ba9703b0 | 28 | |
a2a8927a XL |
29 | #[unstable(feature = "future_join", issue = "91642")] |
30 | pub use self::join::join; | |
31 | ||
f9f354fc XL |
32 | #[unstable(feature = "into_future", issue = "67644")] |
33 | pub use into_future::IntoFuture; | |
34 | ||
1b1a35ee | 35 | #[stable(feature = "future_readiness_fns", since = "1.48.0")] |
f9f354fc | 36 | pub use pending::{pending, Pending}; |
1b1a35ee | 37 | #[stable(feature = "future_readiness_fns", since = "1.48.0")] |
f9f354fc XL |
38 | pub use ready::{ready, Ready}; |
39 | ||
f035d41b XL |
40 | #[unstable(feature = "future_poll_fn", issue = "72302")] |
41 | pub use poll_fn::{poll_fn, PollFn}; | |
42 | ||
ba9703b0 XL |
43 | /// This type is needed because: |
44 | /// | |
45 | /// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass | |
29967ef6 | 46 | /// a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>). |
ba9703b0 XL |
47 | /// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future |
48 | /// non-Send/Sync as well, and we don't want that. | |
49 | /// | |
50 | /// It also simplifies the HIR lowering of `.await`. | |
51 | #[doc(hidden)] | |
52 | #[unstable(feature = "gen_future", issue = "50547")] | |
ba9703b0 XL |
53 | #[derive(Debug, Copy, Clone)] |
54 | pub struct ResumeTy(NonNull<Context<'static>>); | |
55 | ||
56 | #[unstable(feature = "gen_future", issue = "50547")] | |
ba9703b0 XL |
57 | unsafe impl Send for ResumeTy {} |
58 | ||
59 | #[unstable(feature = "gen_future", issue = "50547")] | |
ba9703b0 XL |
60 | unsafe impl Sync for ResumeTy {} |
61 | ||
62 | /// Wrap a generator in a future. | |
63 | /// | |
64 | /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give | |
65 | /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). | |
66 | // This is `const` to avoid extra errors after we recover from `const async fn` | |
1b1a35ee | 67 | #[lang = "from_generator"] |
ba9703b0 XL |
68 | #[doc(hidden)] |
69 | #[unstable(feature = "gen_future", issue = "50547")] | |
1b1a35ee | 70 | #[rustc_const_unstable(feature = "gen_future", issue = "50547")] |
ba9703b0 XL |
71 | #[inline] |
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | |
73 | where | |
74 | T: Generator<ResumeTy, Yield = ()>, | |
75 | { | |
f035d41b | 76 | #[rustc_diagnostic_item = "gen_future"] |
ba9703b0 XL |
77 | struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T); |
78 | ||
79 | // We rely on the fact that async/await futures are immovable in order to create | |
80 | // self-referential borrows in the underlying generator. | |
81 | impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {} | |
82 | ||
83 | impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> { | |
84 | type Output = T::Return; | |
85 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | |
1b1a35ee | 86 | // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. |
ba9703b0 XL |
87 | let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; |
88 | ||
89 | // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The | |
90 | // `.await` lowering will safely cast that back to a `&mut Context`. | |
91 | match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) { | |
92 | GeneratorState::Yielded(()) => Poll::Pending, | |
93 | GeneratorState::Complete(x) => Poll::Ready(x), | |
94 | } | |
95 | } | |
96 | } | |
97 | ||
98 | GenFuture(gen) | |
99 | } | |
100 | ||
1b1a35ee | 101 | #[lang = "get_context"] |
ba9703b0 XL |
102 | #[doc(hidden)] |
103 | #[unstable(feature = "gen_future", issue = "50547")] | |
3c0e092e | 104 | #[must_use] |
ba9703b0 XL |
105 | #[inline] |
106 | pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { | |
f035d41b XL |
107 | // SAFETY: the caller must guarantee that `cx.0` is a valid pointer |
108 | // that fulfills all the requirements for a mutable reference. | |
109 | unsafe { &mut *cx.0.as_ptr().cast() } | |
ba9703b0 | 110 | } |