Search code examples
rustgeneratorresume

Generator does not seem to expose `resume()` method


I was having a look at generators in Rust, and decided to give it a try. I implemented the most basic example I could come find:

#![feature(generators, generator_trait)]

use std::ops::Generator;

fn main() {
    let mut generator = || {
        println!("2");
        yield;
        println!("4");
    };

    println!("1");
    generator.resume();
    println!("3");
    generator.resume();
    println!("5");
}

However, when I try to compile I get this error:

error[E0599]: no method named `resume` found for type `[generator@src/main.rs:6:25: 10:6 _]` in the current scope
  --> src/main.rs:13:15
   |
13 |     generator.resume();
   |               ^^^^^^

Am I doing something wrong or the resume() method actually does not exist on generators? If so, how can I wake up a generator? The documentation I could find all points to the resume() method, so I am confused now.

Note: Yes, I am aware that this is an unstable feature of the language, but on the doc it does encourage users to try and use it, so I am assuming it should be at least partially implemented?

My current environment: rustc 1.35.0-nightly (acd8dd6a5 2019-04-05)


Solution

  • Yes, I am aware that this is an unstable feature

    Unstable features tend to change over time and this is the case. With the recent stabilization of Pin the signature of resume has been changed (PR #55704)

    fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
    

    But fortunately the examples has also been adopted.

    So your code needs to look like this:

    #![feature(generators, generator_trait)]
    
    use std::ops::Generator;
    use std::pin::Pin;
    
    fn main() {
        let mut generator = || {
            println!("2");
            yield;
            println!("4");
        };
    
        let mut pin = Pin::new(&mut generator);
        println!("1");
        pin.as_mut().resume();
        println!("3");
        pin.as_mut().resume();
        println!("5");
    }
    

    The upside of this is, that this approach does not need unsafe anymore (which your code is missing and therefore should not compile on an older nightly) and that's why the Pin API has been choosen for the generator.

    Lessons learned: If you are using the nightly compiler, also use the nightly doc.