]>
Commit | Line | Data |
---|---|---|
1 | #![stable(feature = "futures_api", since = "1.36.0")] | |
2 | ||
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/ | |
11 | ||
12 | use crate::{ | |
13 | ops::{Generator, GeneratorState}, | |
14 | pin::Pin, | |
15 | ptr::NonNull, | |
16 | task::{Context, Poll}, | |
17 | }; | |
18 | ||
19 | mod future; | |
20 | mod into_future; | |
21 | mod join; | |
22 | mod pending; | |
23 | mod poll_fn; | |
24 | mod ready; | |
25 | ||
26 | #[stable(feature = "futures_api", since = "1.36.0")] | |
27 | pub use self::future::Future; | |
28 | ||
29 | #[unstable(feature = "future_join", issue = "91642")] | |
30 | pub use self::join::join; | |
31 | ||
32 | #[unstable(feature = "into_future", issue = "67644")] | |
33 | pub use into_future::IntoFuture; | |
34 | ||
35 | #[stable(feature = "future_readiness_fns", since = "1.48.0")] | |
36 | pub use pending::{pending, Pending}; | |
37 | #[stable(feature = "future_readiness_fns", since = "1.48.0")] | |
38 | pub use ready::{ready, Ready}; | |
39 | ||
40 | #[unstable(feature = "future_poll_fn", issue = "72302")] | |
41 | pub use poll_fn::{poll_fn, PollFn}; | |
42 | ||
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 | |
46 | /// a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>). | |
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")] | |
53 | #[derive(Debug, Copy, Clone)] | |
54 | pub struct ResumeTy(NonNull<Context<'static>>); | |
55 | ||
56 | #[unstable(feature = "gen_future", issue = "50547")] | |
57 | unsafe impl Send for ResumeTy {} | |
58 | ||
59 | #[unstable(feature = "gen_future", issue = "50547")] | |
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` | |
67 | #[lang = "from_generator"] | |
68 | #[doc(hidden)] | |
69 | #[unstable(feature = "gen_future", issue = "50547")] | |
70 | #[rustc_const_unstable(feature = "gen_future", issue = "50547")] | |
71 | #[inline] | |
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | |
73 | where | |
74 | T: Generator<ResumeTy, Yield = ()>, | |
75 | { | |
76 | #[rustc_diagnostic_item = "gen_future"] | |
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> { | |
86 | // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. | |
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 | ||
101 | #[lang = "get_context"] | |
102 | #[doc(hidden)] | |
103 | #[unstable(feature = "gen_future", issue = "50547")] | |
104 | #[must_use] | |
105 | #[inline] | |
106 | pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { | |
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() } | |
110 | } |