summaryrefslogtreecommitdiffstats
path: root/library/core/src/ops/generator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/ops/generator.rs')
-rw-r--r--library/core/src/ops/generator.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs
new file mode 100644
index 000000000..b651b7b23
--- /dev/null
+++ b/library/core/src/ops/generator.rs
@@ -0,0 +1,136 @@
+use crate::marker::Unpin;
+use crate::pin::Pin;
+
+/// The result of a generator resumption.
+///
+/// This enum is returned from the `Generator::resume` method and indicates the
+/// possible return values of a generator. Currently this corresponds to either
+/// a suspension point (`Yielded`) or a termination point (`Complete`).
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[lang = "generator_state"]
+#[unstable(feature = "generator_trait", issue = "43122")]
+pub enum GeneratorState<Y, R> {
+ /// The generator suspended with a value.
+ ///
+ /// This state indicates that a generator has been suspended, and typically
+ /// corresponds to a `yield` statement. The value provided in this variant
+ /// corresponds to the expression passed to `yield` and allows generators to
+ /// provide a value each time they yield.
+ Yielded(Y),
+
+ /// The generator completed with a return value.
+ ///
+ /// This state indicates that a generator has finished execution with the
+ /// provided value. Once a generator has returned `Complete` it is
+ /// considered a programmer error to call `resume` again.
+ Complete(R),
+}
+
+/// The trait implemented by builtin generator types.
+///
+/// Generators, also commonly referred to as coroutines, are currently an
+/// experimental language feature in Rust. Added in [RFC 2033] generators are
+/// currently intended to primarily provide a building block for async/await
+/// syntax but will likely extend to also providing an ergonomic definition for
+/// iterators and other primitives.
+///
+/// The syntax and semantics for generators is unstable and will require a
+/// further RFC for stabilization. At this time, though, the syntax is
+/// closure-like:
+///
+/// ```rust
+/// #![feature(generators, generator_trait)]
+///
+/// use std::ops::{Generator, GeneratorState};
+/// use std::pin::Pin;
+///
+/// fn main() {
+/// let mut generator = || {
+/// yield 1;
+/// "foo"
+/// };
+///
+/// match Pin::new(&mut generator).resume(()) {
+/// GeneratorState::Yielded(1) => {}
+/// _ => panic!("unexpected return from resume"),
+/// }
+/// match Pin::new(&mut generator).resume(()) {
+/// GeneratorState::Complete("foo") => {}
+/// _ => panic!("unexpected return from resume"),
+/// }
+/// }
+/// ```
+///
+/// More documentation of generators can be found in the [unstable book].
+///
+/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
+/// [unstable book]: ../../unstable-book/language-features/generators.html
+#[lang = "generator"]
+#[unstable(feature = "generator_trait", issue = "43122")]
+#[fundamental]
+pub trait Generator<R = ()> {
+ /// The type of value this generator yields.
+ ///
+ /// This associated type corresponds to the `yield` expression and the
+ /// values which are allowed to be returned each time a generator yields.
+ /// For example an iterator-as-a-generator would likely have this type as
+ /// `T`, the type being iterated over.
+ type Yield;
+
+ /// The type of value this generator returns.
+ ///
+ /// This corresponds to the type returned from a generator either with a
+ /// `return` statement or implicitly as the last expression of a generator
+ /// literal. For example futures would use this as `Result<T, E>` as it
+ /// represents a completed future.
+ #[lang = "generator_return"]
+ type Return;
+
+ /// Resumes the execution of this generator.
+ ///
+ /// This function will resume execution of the generator or start execution
+ /// if it hasn't already. This call will return back into the generator's
+ /// last suspension point, resuming execution from the latest `yield`. The
+ /// generator will continue executing until it either yields or returns, at
+ /// which point this function will return.
+ ///
+ /// # Return value
+ ///
+ /// The `GeneratorState` enum returned from this function indicates what
+ /// state the generator is in upon returning. If the `Yielded` variant is
+ /// returned then the generator has reached a suspension point and a value
+ /// has been yielded out. Generators in this state are available for
+ /// resumption at a later point.
+ ///
+ /// If `Complete` is returned then the generator has completely finished
+ /// with the value provided. It is invalid for the generator to be resumed
+ /// again.
+ ///
+ /// # Panics
+ ///
+ /// This function may panic if it is called after the `Complete` variant has
+ /// been returned previously. While generator literals in the language are
+ /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
+ /// for all implementations of the `Generator` trait.
+ fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
+}
+
+#[unstable(feature = "generator_trait", issue = "43122")]
+impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
+ type Yield = G::Yield;
+ type Return = G::Return;
+
+ fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+ G::resume((*self).as_mut(), arg)
+ }
+}
+
+#[unstable(feature = "generator_trait", issue = "43122")]
+impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
+ type Yield = G::Yield;
+ type Return = G::Return;
+
+ fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+ G::resume(Pin::new(&mut *self), arg)
+ }
+}