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

Closed
anderspapitto opened this issue Feb 22, 2019 · 4 comments · Fixed by #96686
Closed

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

anderspapitto opened this issue Feb 22, 2019 · 4 comments · Fixed by #96686
Assignees
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` requires-nightly This issue requires a nightly compiler in some way.

Comments

@anderspapitto
Copy link
Contributor

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
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.

@Centril Centril added the A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. label Feb 23, 2019
@cramertj
Copy link
Member

cc @oli-obk

@oli-obk
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
@Centril Centril added F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` requires-nightly This issue requires a nightly compiler in some way. labels Jul 28, 2019
@jackh726
Copy link
Member

jackh726 commented Feb 3, 2021

This is fixed in master.
A more minimal example that probably still failed previously (needs to be checked) that doesn't depend on rand or never type:

#![feature(generators, generator_trait)]
#![feature(type_alias_impl_trait)]
#![allow(unused)]

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

type RandGenerator<'a> = impl Generator<Return=(), Yield=u64> + 'a;
fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> {
    move || {
        let _rng = rng;
        loop {
            yield 0;
        };
    }
}

type RandGeneratorWithIndirection<'a> = impl Generator<Return=(), Yield=u64> + 'a;
fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> {
    fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return=(), Yield=u64> {
        move || {
            let _rng = rng;
            loop {
                yield 0;
            };
        }
    }

    helper(rng)
}

fn main() {
    let mut gen = rand_generator(&());
    match unsafe { Pin::new_unchecked(&mut gen) }.resume(()) {
        GeneratorState::Yielded(_) => { }
        GeneratorState::Complete(_) => { }
    };
}

playground

@jackh726 jackh726 added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Feb 3, 2021
@bors bors closed this as completed in 2ca778f May 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` requires-nightly This issue requires a nightly compiler in some way.
Development

Successfully merging a pull request may close this issue.

5 participants