use crate::pin::Pin; /// The result of a coroutine resumption. /// /// This enum is returned from the `Coroutine::resume` method and indicates the /// possible return values of a coroutine. Currently this corresponds to either /// a suspension point (`Yielded`) or a termination point (`Complete`). #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[lang = "coroutine_state"] #[unstable(feature = "coroutine_trait", issue = "43122")] pub enum CoroutineState { /// The coroutine suspended with a value. /// /// This state indicates that a coroutine has been suspended, and typically /// corresponds to a `yield` statement. The value provided in this variant /// corresponds to the expression passed to `yield` and allows coroutines to /// provide a value each time they yield. Yielded(Y), /// The coroutine completed with a return value. /// /// This state indicates that a coroutine has finished execution with the /// provided value. Once a coroutine has returned `Complete` it is /// considered a programmer error to call `resume` again. Complete(R), } /// The trait implemented by builtin coroutine types. /// /// Coroutines are currently an /// experimental language feature in Rust. Added in [RFC 2033] coroutines are /// currently intended to primarily provide a building block for async/await /// syntax but will likely extend to also providing an ergonomic definition for /// iterators and other primitives. /// /// The syntax and semantics for coroutines is unstable and will require a /// further RFC for stabilization. At this time, though, the syntax is /// closure-like: /// /// ```rust /// #![feature(coroutines)] /// #![feature(coroutine_trait)] /// /// use std::ops::{Coroutine, CoroutineState}; /// use std::pin::Pin; /// /// fn main() { /// let mut coroutine = || { /// yield 1; /// "foo" /// }; /// /// match Pin::new(&mut coroutine).resume(()) { /// CoroutineState::Yielded(1) => {} /// _ => panic!("unexpected return from resume"), /// } /// match Pin::new(&mut coroutine).resume(()) { /// CoroutineState::Complete("foo") => {} /// _ => panic!("unexpected return from resume"), /// } /// } /// ``` /// /// More documentation of coroutines can be found in the [unstable book]. /// /// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 /// [unstable book]: ../../unstable-book/language-features/coroutines.html #[lang = "coroutine"] #[unstable(feature = "coroutine_trait", issue = "43122")] #[fundamental] pub trait Coroutine { /// The type of value this coroutine yields. /// /// This associated type corresponds to the `yield` expression and the /// values which are allowed to be returned each time a coroutine yields. /// For example an iterator-as-a-coroutine would likely have this type as /// `T`, the type being iterated over. type Yield; /// The type of value this coroutine returns. /// /// This corresponds to the type returned from a coroutine either with a /// `return` statement or implicitly as the last expression of a coroutine /// literal. For example futures would use this as `Result` as it /// represents a completed future. type Return; /// Resumes the execution of this coroutine. /// /// This function will resume execution of the coroutine or start execution /// if it hasn't already. This call will return back into the coroutine's /// last suspension point, resuming execution from the latest `yield`. The /// coroutine will continue executing until it either yields or returns, at /// which point this function will return. /// /// # Return value /// /// The `CoroutineState` enum returned from this function indicates what /// state the coroutine is in upon returning. If the `Yielded` variant is /// returned then the coroutine has reached a suspension point and a value /// has been yielded out. Coroutines in this state are available for /// resumption at a later point. /// /// If `Complete` is returned then the coroutine has completely finished /// with the value provided. It is invalid for the coroutine to be resumed /// again. /// /// # Panics /// /// This function may panic if it is called after the `Complete` variant has /// been returned previously. While coroutine literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Coroutine` trait. fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState; } #[unstable(feature = "coroutine_trait", issue = "43122")] impl, R> Coroutine for Pin<&mut G> { type Yield = G::Yield; type Return = G::Return; fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { G::resume((*self).as_mut(), arg) } } #[unstable(feature = "coroutine_trait", issue = "43122")] impl + Unpin, R> Coroutine for &mut G { type Yield = G::Yield; type Return = G::Return; fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { G::resume(Pin::new(&mut *self), arg) } }