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