]> git.lizzy.rs Git - rust.git/blob - src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
Auto merge of #98051 - davidtwco:split-dwarf-stabilization, r=wesleywiser
[rust.git] / src / test / ui / lazy-type-alias-impl-trait / freeze_cycle.rs
1 // check-pass
2
3 #![feature(gen_future, generator_trait, negative_impls)]
4
5 use std::ops::{Generator, GeneratorState};
6 use std::task::{Poll, Context};
7 use std::future::{Future};
8 use std::ptr::NonNull;
9 use std::pin::Pin;
10
11 fn main() {}
12
13 #[derive(Debug, Copy, Clone)]
14 pub struct ResumeTy(NonNull<Context<'static>>);
15
16 unsafe impl Send for ResumeTy {}
17
18 unsafe impl Sync for ResumeTy {}
19
20 pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
21 where
22     T: Generator<ResumeTy, Yield = ()>,
23 {
24     struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
25
26     // We rely on the fact that async/await futures are immovable in order to create
27     // self-referential borrows in the underlying generator.
28     impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
29
30     impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
31         type Output = T::Return;
32         fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
33             // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
34             let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
35
36             // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
37             // `.await` lowering will safely cast that back to a `&mut Context`.
38             match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
39                 GeneratorState::Yielded(()) => Poll::Pending,
40                 GeneratorState::Complete(x) => Poll::Ready(x),
41             }
42         }
43     }
44
45     GenFuture(gen)
46 }