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