0

I am trying to port this python prime number generator to rust using rust generators and this generator-to-iterator wrapper.

My problem is that the original implementation is recursive, and I didn't manage to get passed the following error:

error[E0720]: opaque type expands to a recursive type
  --> src/main.rs:27:29
   |
27 | fn recursive_generator() -> impl Iterator<Item = u64> {
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ expands to a recursive type
   |
   = note: expanded type is `GeneratorToIterator<[generator@src/main.rs:28:25: 
   48:6 {u64, (), impl std::iter::Iterator}]>`

Below is the implementation of the recursive generator producing this error:


fn recursive_generator() -> impl Iterator<Item = u64> {
    GeneratorToIterator(move || {
        // Yield a few values
        yield 1;
        yield 2;
        yield 3;

        // Initialize the inner generator
        let mut inner_value: u64 = 0;
        let mut inner_generator = recursive_generator();

        // Get the first value of the inner generator
        match inner_generator.next(){
             Some(x) => inner_value += x,
             None => {},
        }

        // Yield some other values
        yield 4;
        yield 5;
        yield 6;
    })
}

The full implementation (with the GeneratorToIterator definition) can be found here.

I found this related question but I did not manage to compile their gen_to_iter function.

EDIT: Thanks to @bluss answer, I've finally been able to implement a working version of the prime number generator in rust.

Vincent
  • 12,919
  • 1
  • 42
  • 64

1 Answers1

1

The error explanation E0720 mentions that an impl Trait type must expand to one that doesn't contain other impl Trait types, but here the type is of course recursive, since that's the point.

This can be worked around by using boxed trait objects instead - Box<Iterator<Item=u64>> works well here and avoids the problem.

Either adjust recursive_generator to return Box<Iterator<Item=u64>>, or change the line of the recursive call to use the boxed iterator just for that recursive case.

bluss
  • 12,472
  • 1
  • 49
  • 48
  • 1
    Thanks a lot, I just tried and both approaches work just fine! For the second solution I had to use [`let mut inner_generator: Box> = Box::new(recursive_generator());`](https://gist.github.com/vxgmichel/45ddea42c6965927761e51d3f0a1213b#file-recgen-rs-L36-L37), can you confirm that this is what you meant? – Vincent Oct 12 '19 at 16:13
  • Yes, exactly. Your version with coercion or this version with cast are equivalent: `Box::new(f()) as Box` – bluss Oct 12 '19 at 18:48
  • Thanks again, I finally managed to get [my implementation](https://gist.github.com/vxgmichel/95b769bc9b2c68bfcbb2fbcc86cac919#file-primegen-rs) to work :) – Vincent Oct 12 '19 at 18:59
  • 1
    It reminds me of this https://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf but I don't know the details very well. Have fun :) – bluss Oct 12 '19 at 19:02