]> git.lizzy.rs Git - rust.git/blob - library/core/src/ops/generator.rs
Merge commit '2b2190cb5667cdd276a24ef8b9f3692209c54a89' into clippyup
[rust.git] / library / core / src / ops / generator.rs
1 use crate::marker::Unpin;
2 use crate::pin::Pin;
3
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)]
10 #[lang = "generator_state"]
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};
45 /// use std::pin::Pin;
46 ///
47 /// fn main() {
48 ///     let mut generator = || {
49 ///         yield 1;
50 ///         "foo"
51 ///     };
52 ///
53 ///     match Pin::new(&mut generator).resume(()) {
54 ///         GeneratorState::Yielded(1) => {}
55 ///         _ => panic!("unexpected return from resume"),
56 ///     }
57 ///     match Pin::new(&mut generator).resume(()) {
58 ///         GeneratorState::Complete("foo") => {}
59 ///         _ => panic!("unexpected return from resume"),
60 ///     }
61 /// }
62 /// ```
63 ///
64 /// More documentation of generators 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/generators.html
68 #[lang = "generator"]
69 #[unstable(feature = "generator_trait", issue = "43122")]
70 #[fundamental]
71 pub trait Generator<R = ()> {
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.
86     #[lang = "generator_return"]
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.
115     fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
116 }
117
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
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 }