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