# A problem with some generators

**URL:** <https://users.rust-lang.org/t/a-problem-with-some-generators/12827>\
**Category:** uncategorized\
**Created:** [September 11, 2017, 8:05pm UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827 "2017-09-11T20:05:18Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![leonardo](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/leonardo/32/1690_2.png) [@leonardo](https://users.rust-lang.org/u/leonardo)\
**Post date:** [September 11, 2017, 8:05pm UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/1 "2017-09-11T20:05:18Z")

</div>

I am playing around with generators, and I've found this problem:

> **[Rust Playground](https://play.rust-lang.org/?gist=d444ef18e929818ed53dfba1b3e4c847&version=nightly)**
>
> A browser interface to the Rust compiler to experiment with the language

```
#![feature(inclusive_range_syntax, generator_trait,
           generators, conservative_impl_trait)]

use std::ops::{Generator, GeneratorState};

fn generator_to_iterator<G>(g: G) -> impl Iterator<Item = G::Yield>
where G: Generator<Return = ()> {
    struct It<G>(G);

    impl<G: Generator<Return = ()>> Iterator for It<G> {
        type Item = G::Yield;

        fn next(&mut self) -> Option<Self::Item> {
            match self.0.resume() {
                GeneratorState::Yielded(y) => Some(y),
                GeneratorState::Complete(()) => None,
            }
        }
    }

    It(g)
}

fn digits_u32(mut n: u32) -> impl Iterator<Item=u32> {
    generator_to_iterator(move || {
        if n == 0 {
            yield 0;
        } else {
            const LEN: usize = 10;
            let mut digits = [0u32; LEN];
            let mut idx = LEN - 1;
            while n != 0 {
                digits[idx] = n % 10;
                n /= 10;
                idx -= 1;
            }
            for &d in &digits[idx + 1 ..] { yield d; }
            //for i in idx + 1 .. LEN { yield digits[i]; }
        }
    })
}

fn main() {
    for i in 0 .. 100 {
        print!("{}: ", i);
        for d in digits_u32(i) {
            print!("{} ", d);
        }
        println!();
    }
}

```

digits\_u32() is supposed to yield the digits of a u32 in order (yielding them in reversed order is simpler), the error it gives is:

```
  --> ...\test.rs:25:5
   |
25 | generator_to_iterator(move || {
   | ^^^^^^^^^^^^^^^^^^^^^ `[u32]` does not have a constant size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `[u32]`
   = note: only the last element of a tuple may have a dynamically sized type

```

As you see from the commented out line I've already found a workaround, but is this supposed to happen, and do you know if there's a better workaround? Thank you.

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 12, 2017, 2:22am UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/2 "2017-09-12T02:22:51Z")

</div>

Interesting example. I suppose the issue is the range operator yields the slice and the closure type storing the slice doesn't work. Changing it to use an iterator, however, runs into "named lifetimes" issue for `impl trait`. I guess one could restructure the code so that the generator is created inside a function that receives a `&'a [u32]` so that we can have a named lifetime for the `impl trait`, but I've not tried this.

I think ideally you'd want to move the array into the generated type for the iterator so that no references are needed to be maintained in the state machine, but I don't immediately see how to do that without your workaround to begin with.

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 12, 2017, 2:29am UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/3 "2017-09-12T02:29:27Z")

</div>

By the way, I'm surprised you didn't post this in [Help test async/await/generators/coroutines! - #33 by Nemo157 - announcements - Rust Internals](https://internals.rust-lang.org/t/help-test-async-await-generators-coroutines/5835/33) 🙂

---

<div class="post-metadata">

**Author:** ![leonardo](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/leonardo/32/1690_2.png) [@leonardo](https://users.rust-lang.org/u/leonardo)\
**Post date:** [September 12, 2017, 5:08am UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/4 "2017-09-12T05:08:21Z")

</div>

> [@vitalyd](#):
>
> By the way, I’m surprised you didn’t post this in

In a sense, I did, but I was ignored (when I tried to implement that function I had the same problem):

> **[Help test async/await/generators/coroutines!](https://internals.rust-lang.org/t/help-test-async-await-generators-coroutines/5835/20?u=leonardo)**
>
> Can you use that on this function too? // pairwise(1 2 3) =\> (1, 1) (1, 2) (1, 3) (2, 2) (2, 3) (3, 3) fn pairwise\<'a, T\>(items: &'a \[T\]) -\> impl Iterator + 'a { items .iter() .enumerate() .flat\_map(move |(i, x1)|...

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 12, 2017, 12:19pm UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/5 "2017-09-12T12:19:11Z")

</div>

> [@vitalyd](#):
>
> I guess one could restructure the code so that the generator is created inside a function that receives a &'a [u32] so that we can have a named lifetime for the impl trait, but I’ve not tried this.

So that's this, which works:

```rust
fn digits_u32<'a>(mut n: u32, digits: &'a mut [u32; 10]) -> impl Iterator<Item=u32> + 'a {
    generator_to_iterator(move || {
        if n == 0 {
            yield 0;
        } else {
            let mut idx = digits.len() - 1;
            while n != 0 {
                digits[idx] = n % 10;
                n /= 10;
                idx -= 1;
            }
            for &d in digits[idx + 1 ..].iter() { yield d; }
        }
    })
}
```

Of course this is pretty bad, and much worse than your original workaround. As mentioned, it seems like the problem is that the iterator over the array requires a reference to the array, and this then means the compiler generated `impl Iterator` has a lifetime associated with it. The lifetime is to a local array, which is also captured in the closure (I suspect) so it stays live across yields. Then it sounds like we'll get into the self-referential struct case where the closure both has the array and also an iterator that references the array. I could be wrong though. I'd be interested to hear a definitive explanation on this as well.

---

<div class="post-metadata">

**Author:** ![vadimcn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/vadimcn/32/5123_2.png) [@vadimcn](https://users.rust-lang.org/u/vadimcn)\
**Post date:** [September 13, 2017, 3:08am UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/6 "2017-09-13T03:08:55Z")

</div>

This is not supposed to compile, because generator environment would need to store both the array being iterated over and the iterator borrowing it, which is not allowed for generators, as they must stay movable while suspended.

The error message, on the other hand, is very misleading.

Interestingly, if I don't pass the generator to `generator_to_iterator`, the message is [correct](https://play.rust-lang.org/?gist=74c2f36497efed615c4d1a94a58d9f3e&version=nightly):

```rust
error[E0626]: borrow may still be in use when generator yields
  --> src/main.rs:37:24
   |
37 | for &d in &digits[idx + 1 ..] { yield d; }
   | ^^^^^^ ------- possible yield occurs here

```

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [January 12, 2023, 8:45am UTC](https://users.rust-lang.org/t/a-problem-with-some-generators/12827/7 "2023-01-12T08:45:31Z")

</div>


