// check-pass #![feature(coroutine_trait, negative_impls)] use std::ops::{Coroutine, CoroutineState}; use std::task::{Poll, Context}; use std::future::{Future}; use std::ptr::NonNull; use std::pin::Pin; fn main() {} #[derive(Debug, Copy, Clone)] pub struct ResumeTy(NonNull>); unsafe impl Send for ResumeTy {} unsafe impl Sync for ResumeTy {} pub const fn from_coroutine(gen: T) -> impl Future where T: Coroutine, { struct GenFuture>(T); // We rely on the fact that async/await futures are immovable in order to create // self-referential borrows in the underlying coroutine. impl> !Unpin for GenFuture {} impl> Future for GenFuture { type Output = T::Return; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; // Resume the coroutine, turning the `&mut Context` into a `NonNull` raw pointer. The // `.await` lowering will safely cast that back to a `&mut Context`. match gen.resume(ResumeTy(NonNull::from(cx).cast::>())) { CoroutineState::Yielded(()) => Poll::Pending, CoroutineState::Complete(x) => Poll::Ready(x), } } } GenFuture(gen) }