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 type` complains about `'_` in concrete type of self-borrowing generators #60655

Closed
cramertj opened this issue May 9, 2019 · 6 comments

Comments

Projects
None yet
3 participants
@cramertj
Copy link
Member

commented May 9, 2019

Playground

error: non-defining existential type use in defining scope
  --> src/main.rs:9:22
   |
9  |   fn bar() -> ServeFut {
   |  ______________________^
10 | |     async move {
11 | |         let x = 5;
12 | |         await!(foo(&x))
13 | |     }
14 | | }
   | |_^ lifetime `'_` is part of concrete type but not used in parameter list of existential type

error: aborting due to previous error

cc @oli-obk

@oli-obk

This comment has been minimized.

Copy link
Contributor

commented May 9, 2019

Am I correct in assuming that this should not compile, but report an error about returning a reference to the local variable x? Or is the self-borrowing generator part what makes this work? so the x is part of the generator struct and the &x is the yielded thing?

I'll try pretty printing to the expanded HIR, since I'm not sure what's going on there

@oli-obk

This comment has been minimized.

Copy link
Contributor

commented May 9, 2019

Expanded version:

#![feature(gen_future)]
#![feature(generators)]
#![feature(async_await, await_macro, existential_type)]

use std::future::{self, Future};

async fn foo(__arg0: &u8) {
}

pub existential type ServeFut: Future<Output = ()>;

fn bar() -> ServeFut {
    ::std::future::from_generator(move || {
        let x = 5;

        {
            let mut pinned = foo(&x);
            loop {
                match future::poll_with_tls_context(unsafe {
                    std::pin::Pin::new_unchecked(&mut pinned)
                }) {
                    std::task::Poll::Ready(x) => {
                        break x;
                    }
                    _ => (),
                }
                yield ()
            }
        }
    })
}
fn main() {}

Playground

@cramertj

This comment has been minimized.

Copy link
Member Author

commented May 9, 2019

Am I correct in assuming that this should not compile, but report an error about returning a reference to the local variable x?

No, this should definitely compile.

Or is the self-borrowing generator part what makes this work? so the x is part of the generator struct and the &x is the yielded thing?

&x isn't yielded, but yes, it's a local variable inside the generator (that references another local variable in the generator).

@oli-obk

This comment has been minimized.

Copy link
Contributor

commented May 10, 2019

Hmm, so because the generator contains references, it has lifetimes, but these lifetimes actually refer to the generator again? Do we have a special kind of lifetime that we use for this? We should just ignore those generator lifetimes for existential types.

@cramertj

This comment has been minimized.

Copy link
Member Author

commented May 10, 2019

There's no special lifetime afaik (cc @Zoxc @tmandry).

@matthewjasper

This comment has been minimized.

Copy link
Contributor

commented May 12, 2019

We should ignore all bound regions. Function pointers have the same issue:

existential type A: Sized;

fn foo() -> A {
    (|x| ()) as for<'a> fn(&'a i32)
}

fn main() {}

Centril added a commit to Centril/rust that referenced this issue May 14, 2019

Rollup merge of rust-lang#60799 - matthewjasper:allow-bound-regions-i…
…n-existential-types, r=oli-obk

Allow late-bound regions in existential types

closes rust-lang#60655
r? @oli-obk

@bors bors closed this in #60799 May 14, 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.