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