Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

existential Generator + lifetime type errors unless impl trait wrapper is used #58662

Open
anderspapitto opened this Issue Feb 22, 2019 · 3 comments

Comments

Projects
None yet
4 participants
@anderspapitto
Copy link
Contributor

anderspapitto commented Feb 22, 2019

I'm writing a simple Generator that takes a reference to an RNG, and yields values from it. This makes sense as long as the generator doesn't outlive the RNG which it references.

I want to name the type of the generator with an existential type, but I can't do so unless I wrap a version of the function that uses an impl Trait formulation.

Here's the direct version which doesn't work

existential type RandGenerator<'a>: 'a + Generator<Return=!, Yield=u64>;
fn rand_generator<'a>(rng: &'a mut MyRng) -> RandGenerator<'a> {
    move || {
        loop {
            yield rng.gen::<u64>();
        };
    }
}

and here's the more convoluted version which does

existential type RandGeneratorWithIndirection<'a>: 'a + Generator<Return=!, Yield=u64>;
fn rand_generator_with_indirection<'a>(rng: &'a mut MyRng) -> RandGeneratorWithIndirection<'a> {
    fn helper<'b>(rng: &'b mut MyRng) -> impl 'b + Generator<Return=!, Yield=u64> {
        move || {
            loop {
                yield rng.gen::<u64>();
            };
        }
    }

    helper(rng)
}

and here's a playground link containing both versions, as well as a bit of scaffolding

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=7c7b6ce96c2f1b7d5d4a4c3d2d65a33f

The full error message I'm seeing looks like this

   Compiling playground v0.0.1 (/playground)
error: non-defining existential type use in defining scope
  --> src/main.rs:16:64
   |
16 |   fn rand_generator<'a>(rng: &'a mut MyRng) -> RandGenerator<'a> {
   |  ________________________________________________________________^
17 | |     move || {
18 | |         loop {
19 | |             yield rng.gen::<u64>();
20 | |         };
21 | |     }
22 | | }
   | |_^ lifetime `` is part of concrete type but not used in parameter list of existential type

error: aborting due to previous error

error: Could not compile `playground`.

To learn more, run the command again with --verbose.
@anderspapitto

This comment has been minimized.

Copy link
Contributor Author

anderspapitto commented Feb 22, 2019

I don't know if this properly counts as a compiler bug, but it feels like one because the "fix" is a very mechanical code transformation.

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Feb 23, 2019

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Feb 23, 2019

Yea that's definitely a bug. I'll investigate where this unnamed lifetime is coming from. Maybe I'm accidentally erasing lifetimes somewhere

@oli-obk oli-obk self-assigned this Feb 23, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.