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