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 | /// |
44 | /// use std::ops::{Coroutine, CoroutineState}; |
45 | /// use std::pin::Pin; |
46 | /// |
47 | /// fn main() { |
48 | /// let mut coroutine = || { |
49 | /// yield 1; |
50 | /// "foo" |
51 | /// }; |
52 | /// |
53 | /// match Pin::new(&mut coroutine).resume(()) { |
54 | /// CoroutineState::Yielded(1) => {} |
55 | /// _ => panic!("unexpected return from resume" ), |
56 | /// } |
57 | /// match Pin::new(&mut coroutine).resume(()) { |
58 | /// CoroutineState::Complete("foo" ) => {} |
59 | /// _ => panic!("unexpected return from resume" ), |
60 | /// } |
61 | /// } |
62 | /// ``` |
63 | /// |
64 | /// More documentation of coroutines can be found in the [unstable book]. |
65 | /// |
66 | /// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 |
67 | /// [unstable book]: ../../unstable-book/language-features/coroutines.html |
68 | #[lang = "coroutine" ] |
69 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
70 | #[fundamental ] |
71 | pub trait Coroutine<R = ()> { |
72 | /// The type of value this coroutine yields. |
73 | /// |
74 | /// This associated type corresponds to the `yield` expression and the |
75 | /// values which are allowed to be returned each time a coroutine yields. |
76 | /// For example an iterator-as-a-coroutine would likely have this type as |
77 | /// `T`, the type being iterated over. |
78 | type Yield; |
79 | |
80 | /// The type of value this coroutine returns. |
81 | /// |
82 | /// This corresponds to the type returned from a coroutine either with a |
83 | /// `return` statement or implicitly as the last expression of a coroutine |
84 | /// literal. For example futures would use this as `Result<T, E>` as it |
85 | /// represents a completed future. |
86 | type Return; |
87 | |
88 | /// Resumes the execution of this coroutine. |
89 | /// |
90 | /// This function will resume execution of the coroutine or start execution |
91 | /// if it hasn't already. This call will return back into the coroutine's |
92 | /// last suspension point, resuming execution from the latest `yield`. The |
93 | /// coroutine will continue executing until it either yields or returns, at |
94 | /// which point this function will return. |
95 | /// |
96 | /// # Return value |
97 | /// |
98 | /// The `CoroutineState` enum returned from this function indicates what |
99 | /// state the coroutine is in upon returning. If the `Yielded` variant is |
100 | /// returned then the coroutine has reached a suspension point and a value |
101 | /// has been yielded out. Coroutines in this state are available for |
102 | /// resumption at a later point. |
103 | /// |
104 | /// If `Complete` is returned then the coroutine has completely finished |
105 | /// with the value provided. It is invalid for the coroutine to be resumed |
106 | /// again. |
107 | /// |
108 | /// # Panics |
109 | /// |
110 | /// This function may panic if it is called after the `Complete` variant has |
111 | /// been returned previously. While coroutine literals in the language are |
112 | /// guaranteed to panic on resuming after `Complete`, this is not guaranteed |
113 | /// for all implementations of the `Coroutine` trait. |
114 | #[cfg_attr (not(bootstrap), lang = "coroutine_resume" )] |
115 | fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>; |
116 | } |
117 | |
118 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
119 | impl<G: ?Sized + Coroutine<R>, R> Coroutine<R> for Pin<&mut G> { |
120 | type Yield = G::Yield; |
121 | type Return = G::Return; |
122 | |
123 | fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
124 | G::resume((*self).as_mut(), arg) |
125 | } |
126 | } |
127 | |
128 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] |
129 | impl<G: ?Sized + Coroutine<R> + Unpin, R> Coroutine<R> for &mut G { |
130 | type Yield = G::Yield; |
131 | type Return = G::Return; |
132 | |
133 | fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
134 | G::resume(self:Pin::new(&mut *self), arg) |
135 | } |
136 | } |
137 | |