Skip to main content

core/ops/
coroutine.rs

1use 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(#[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::clone::Clone, R: crate::clone::Clone> crate::clone::Clone for
    CoroutineState<Y, R> {
    #[inline]
    fn clone(&self) -> CoroutineState<Y, R> {
        match self {
            CoroutineState::Yielded(__self_0) =>
                CoroutineState::Yielded(crate::clone::Clone::clone(__self_0)),
            CoroutineState::Complete(__self_0) =>
                CoroutineState::Complete(crate::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::marker::Copy, R: crate::marker::Copy> crate::marker::Copy for
    CoroutineState<Y, R> {
}Copy, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::cmp::PartialEq, R: crate::cmp::PartialEq> crate::cmp::PartialEq
    for CoroutineState<Y, R> {
    #[inline]
    fn eq(&self, other: &CoroutineState<Y, R>) -> bool {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        let __arg1_discr = crate::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (CoroutineState::Yielded(__self_0),
                    CoroutineState::Yielded(__arg1_0)) => __self_0 == __arg1_0,
                (CoroutineState::Complete(__self_0),
                    CoroutineState::Complete(__arg1_0)) => __self_0 == __arg1_0,
                _ => unsafe { crate::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::cmp::PartialOrd, R: crate::cmp::PartialOrd>
    crate::cmp::PartialOrd for CoroutineState<Y, R> {
    #[inline]
    fn partial_cmp(&self, other: &CoroutineState<Y, R>)
        -> crate::option::Option<crate::cmp::Ordering> {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        let __arg1_discr = crate::intrinsics::discriminant_value(other);
        match (self, other) {
            (CoroutineState::Yielded(__self_0),
                CoroutineState::Yielded(__arg1_0)) =>
                crate::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (CoroutineState::Complete(__self_0),
                CoroutineState::Complete(__arg1_0)) =>
                crate::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            _ =>
                crate::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::cmp::Eq, R: crate::cmp::Eq> crate::cmp::Eq for
    CoroutineState<Y, R> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: crate::cmp::AssertParamIsEq<Y>;
        let _: crate::cmp::AssertParamIsEq<R>;
    }
}Eq, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::cmp::Ord, R: crate::cmp::Ord> crate::cmp::Ord for
    CoroutineState<Y, R> {
    #[inline]
    fn cmp(&self, other: &CoroutineState<Y, R>) -> crate::cmp::Ordering {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        let __arg1_discr = crate::intrinsics::discriminant_value(other);
        match crate::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            crate::cmp::Ordering::Equal =>
                match (self, other) {
                    (CoroutineState::Yielded(__self_0),
                        CoroutineState::Yielded(__arg1_0)) =>
                        crate::cmp::Ord::cmp(__self_0, __arg1_0),
                    (CoroutineState::Complete(__self_0),
                        CoroutineState::Complete(__arg1_0)) =>
                        crate::cmp::Ord::cmp(__self_0, __arg1_0),
                    _ => unsafe { crate::intrinsics::unreachable() }
                },
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::fmt::Debug, R: crate::fmt::Debug> crate::fmt::Debug for
    CoroutineState<Y, R> {
    #[inline]
    fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
        match self {
            CoroutineState::Yielded(__self_0) =>
                crate::fmt::Formatter::debug_tuple_field1_finish(f, "Yielded",
                    &__self_0),
            CoroutineState::Complete(__self_0) =>
                crate::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Complete", &__self_0),
        }
    }
}Debug, #[automatically_derived]
#[unstable(feature = "coroutine_trait", issue = "43122")]
impl<Y: crate::hash::Hash, R: crate::hash::Hash> crate::hash::Hash for
    CoroutineState<Y, R> {
    #[inline]
    fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        crate::hash::Hash::hash(&__self_discr, state);
        match self {
            CoroutineState::Yielded(__self_0) =>
                crate::hash::Hash::hash(__self_0, state),
            CoroutineState::Complete(__self_0) =>
                crate::hash::Hash::hash(__self_0, state),
        }
    }
}Hash)]
9#[lang = "coroutine_state"]
10#[unstable(feature = "coroutine_trait", issue = "43122")]
11pub 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 = #[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#[must_use = "coroutines are lazy and do nothing unless resumed"]
73pub trait Coroutine<R = ()> {
74    /// The type of value this coroutine yields.
75    ///
76    /// This associated type corresponds to the `yield` expression and the
77    /// values which are allowed to be returned each time a coroutine yields.
78    /// For example an iterator-as-a-coroutine would likely have this type as
79    /// `T`, the type being iterated over.
80    #[lang = "coroutine_yield"]
81    type Yield;
82
83    /// The type of value this coroutine returns.
84    ///
85    /// This corresponds to the type returned from a coroutine either with a
86    /// `return` statement or implicitly as the last expression of a coroutine
87    /// literal. For example futures would use this as `Result<T, E>` as it
88    /// represents a completed future.
89    #[lang = "coroutine_return"]
90    type Return;
91
92    /// Resumes the execution of this coroutine.
93    ///
94    /// This function will resume execution of the coroutine or start execution
95    /// if it hasn't already. This call will return back into the coroutine's
96    /// last suspension point, resuming execution from the latest `yield`. The
97    /// coroutine will continue executing until it either yields or returns, at
98    /// which point this function will return.
99    ///
100    /// # Return value
101    ///
102    /// The `CoroutineState` enum returned from this function indicates what
103    /// state the coroutine is in upon returning. If the `Yielded` variant is
104    /// returned then the coroutine has reached a suspension point and a value
105    /// has been yielded out. Coroutines in this state are available for
106    /// resumption at a later point.
107    ///
108    /// If `Complete` is returned then the coroutine has completely finished
109    /// with the value provided. It is invalid for the coroutine to be resumed
110    /// again.
111    ///
112    /// # Panics
113    ///
114    /// This function may panic if it is called after the `Complete` variant has
115    /// been returned previously. While coroutine literals in the language are
116    /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
117    /// for all implementations of the `Coroutine` trait.
118    #[lang = "coroutine_resume"]
119    fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>;
120}
121
122#[unstable(feature = "coroutine_trait", issue = "43122")]
123impl<G: ?Sized + Coroutine<R>, R> Coroutine<R> for Pin<&mut G> {
124    type Yield = G::Yield;
125    type Return = G::Return;
126
127    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
128        G::resume((*self).as_mut(), arg)
129    }
130}
131
132#[unstable(feature = "coroutine_trait", issue = "43122")]
133impl<G: ?Sized + Coroutine<R> + Unpin, R> Coroutine<R> for &mut G {
134    type Yield = G::Yield;
135    type Return = G::Return;
136
137    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
138        G::resume(Pin::new(&mut *self), arg)
139    }
140}