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