| 1 | use crate::pin::Pin; |
| 2 | |
| 3 | /// The result of a coroutine resumption. |
| 4 | /// |
| 5 | /// This enum is returned from the `Coroutine::resume` method and indicates the |
| 6 | /// possible return values of a coroutine. Currently this corresponds to either |
| 7 | /// a suspension point (`Yielded`) or a termination point (`Complete`). |
| 8 | #[derive (Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] |
| 9 | #[lang = "coroutine_state" ] |
| 10 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
| 11 | pub enum CoroutineState<Y, R> { |
| 12 | /// The coroutine suspended with a value. |
| 13 | /// |
| 14 | /// This state indicates that a coroutine has been suspended, and typically |
| 15 | /// corresponds to a `yield` statement. The value provided in this variant |
| 16 | /// corresponds to the expression passed to `yield` and allows coroutines to |
| 17 | /// provide a value each time they yield. |
| 18 | Yielded(Y), |
| 19 | |
| 20 | /// The coroutine completed with a return value. |
| 21 | /// |
| 22 | /// This state indicates that a coroutine has finished execution with the |
| 23 | /// provided value. Once a coroutine has returned `Complete` it is |
| 24 | /// considered a programmer error to call `resume` again. |
| 25 | Complete(R), |
| 26 | } |
| 27 | |
| 28 | /// The trait implemented by builtin coroutine types. |
| 29 | /// |
| 30 | /// Coroutines are currently an |
| 31 | /// experimental language feature in Rust. Added in [RFC 2033] coroutines are |
| 32 | /// currently intended to primarily provide a building block for async/await |
| 33 | /// syntax but will likely extend to also providing an ergonomic definition for |
| 34 | /// iterators and other primitives. |
| 35 | /// |
| 36 | /// The syntax and semantics for coroutines is unstable and will require a |
| 37 | /// further RFC for stabilization. At this time, though, the syntax is |
| 38 | /// closure-like: |
| 39 | /// |
| 40 | /// ```rust |
| 41 | /// #![feature(coroutines)] |
| 42 | /// #![feature(coroutine_trait)] |
| 43 | /// #![feature(stmt_expr_attributes)] |
| 44 | /// |
| 45 | /// use std::ops::{Coroutine, CoroutineState}; |
| 46 | /// use std::pin::Pin; |
| 47 | /// |
| 48 | /// fn main() { |
| 49 | /// let mut coroutine = #[coroutine] || { |
| 50 | /// yield 1; |
| 51 | /// "foo" |
| 52 | /// }; |
| 53 | /// |
| 54 | /// match Pin::new(&mut coroutine).resume(()) { |
| 55 | /// CoroutineState::Yielded(1) => {} |
| 56 | /// _ => panic!("unexpected return from resume" ), |
| 57 | /// } |
| 58 | /// match Pin::new(&mut coroutine).resume(()) { |
| 59 | /// CoroutineState::Complete("foo" ) => {} |
| 60 | /// _ => panic!("unexpected return from resume" ), |
| 61 | /// } |
| 62 | /// } |
| 63 | /// ``` |
| 64 | /// |
| 65 | /// More documentation of coroutines can be found in the [unstable book]. |
| 66 | /// |
| 67 | /// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 |
| 68 | /// [unstable book]: ../../unstable-book/language-features/coroutines.html |
| 69 | #[lang = "coroutine" ] |
| 70 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
| 71 | #[fundamental ] |
| 72 | #[must_use = "coroutines are lazy and do nothing unless resumed" ] |
| 73 | pub trait Coroutine<R = ()> { |
| 74 | /// The type of value this coroutine yields. |
| 75 | /// |
| 76 | /// This associated type corresponds to the `yield` expression and the |
| 77 | /// values which are allowed to be returned each time a coroutine yields. |
| 78 | /// For example an iterator-as-a-coroutine would likely have this type as |
| 79 | /// `T`, the type being iterated over. |
| 80 | #[lang = "coroutine_yield" ] |
| 81 | type Yield; |
| 82 | |
| 83 | /// The type of value this coroutine returns. |
| 84 | /// |
| 85 | /// This corresponds to the type returned from a coroutine either with a |
| 86 | /// `return` statement or implicitly as the last expression of a coroutine |
| 87 | /// literal. For example futures would use this as `Result<T, E>` as it |
| 88 | /// represents a completed future. |
| 89 | #[lang = "coroutine_return" ] |
| 90 | type Return; |
| 91 | |
| 92 | /// Resumes the execution of this coroutine. |
| 93 | /// |
| 94 | /// This function will resume execution of the coroutine or start execution |
| 95 | /// if it hasn't already. This call will return back into the coroutine's |
| 96 | /// last suspension point, resuming execution from the latest `yield`. The |
| 97 | /// coroutine will continue executing until it either yields or returns, at |
| 98 | /// which point this function will return. |
| 99 | /// |
| 100 | /// # Return value |
| 101 | /// |
| 102 | /// The `CoroutineState` enum returned from this function indicates what |
| 103 | /// state the coroutine is in upon returning. If the `Yielded` variant is |
| 104 | /// returned then the coroutine has reached a suspension point and a value |
| 105 | /// has been yielded out. Coroutines in this state are available for |
| 106 | /// resumption at a later point. |
| 107 | /// |
| 108 | /// If `Complete` is returned then the coroutine has completely finished |
| 109 | /// with the value provided. It is invalid for the coroutine to be resumed |
| 110 | /// again. |
| 111 | /// |
| 112 | /// # Panics |
| 113 | /// |
| 114 | /// This function may panic if it is called after the `Complete` variant has |
| 115 | /// been returned previously. While coroutine literals in the language are |
| 116 | /// guaranteed to panic on resuming after `Complete`, this is not guaranteed |
| 117 | /// for all implementations of the `Coroutine` trait. |
| 118 | #[lang = "coroutine_resume" ] |
| 119 | fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>; |
| 120 | } |
| 121 | |
| 122 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
| 123 | impl<G: ?Sized + Coroutine<R>, R> Coroutine<R> for Pin<&mut G> { |
| 124 | type Yield = G::Yield; |
| 125 | type Return = G::Return; |
| 126 | |
| 127 | fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
| 128 | G::resume((*self).as_mut(), arg) |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
| 133 | impl<G: ?Sized + Coroutine<R> + Unpin, R> Coroutine<R> for &mut G { |
| 134 | type Yield = G::Yield; |
| 135 | type Return = G::Return; |
| 136 | |
| 137 | fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
| 138 | G::resume(self:Pin::new(&mut *self), arg) |
| 139 | } |
| 140 | } |
| 141 | |