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

non-defining existential type use in defining scope with empty lifetime name #53457

Closed
Nemo157 opened this issue Aug 17, 2018 · 9 comments · Fixed by #61499
Closed

non-defining existential type use in defining scope with empty lifetime name #53457

Nemo157 opened this issue Aug 17, 2018 · 9 comments · Fixed by #61499
Labels
A-closures Area: Closures (`|…| { … }`) A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug.

Comments

@Nemo157
Copy link
Member

Nemo157 commented Aug 17, 2018

Really not sure where the error here is coming from, as far as I can tell there should only be a single relevant lifetime, 'a. The same function written as a free function generic over a Write returning impl Future<...> + 'a works fine (included in the playground). I'll try and come up with a reduced example in the next couple of days (playground)

error: non-defining existential type use in defining scope
  --> src/lib.rs:19:5
   |
19 | /     {
20 | |         poll_fn(move |cx| self.reborrow().poll_close(cx))
21 | |     }
   | |_____^ lifetime `` is part of concrete type but not used in parameter list of existential type
#![feature(arbitrary_self_types, existential_type, pin, futures_api)]

use std::future::Future;
use std::marker::Unpin;
use std::mem::PinMut;
use std::task::{self, Poll};

pub trait Write {
    type Error;

    fn poll_close(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::Error>>;
}

existential type Close<'a, W: Write>: Future<Output = Result<(), W::Error>> + 'a;

trait WriteExt: Write {
    fn close<'a>(self: PinMut<'a, Self>) -> Close<'a, Self>
    where
        Self: Sized,
    {
        poll_fn(move |cx| self.reborrow().poll_close(cx))
    }
}

// ------------
// from futures-util-preview 0.3

pub struct PollFn<F> {
    f: F,
}

impl<F> Unpin for PollFn<F> {}

pub fn poll_fn<T, F>(f: F) -> PollFn<F>
where
    F: FnMut(&mut task::Context) -> Poll<T>,
{
    PollFn { f }
}

impl<T, F> Future for PollFn<F>
where
    F: FnMut(&mut task::Context) -> Poll<T>,
{
    type Output = T;

    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<T> {
        (&mut self.f)(cx)
    }
}

(CC @oli-obk in case you have any hints on where to look)

@Nemo157
Copy link
Member Author

Nemo157 commented Aug 20, 2018

Minimized example (playground)

#![feature(existential_type)]

trait Future {
    fn poll(&self, cx: &mut ());
}

trait Write {
    fn poll_close(&self, cx: &mut ());
}

existential type Close<'a, W: Write>: Future + 'a;

fn broken<'a, W: Write>(w: &'a W) -> Close<'a, W> {
    PollFn(move |cx| w.poll_close(cx))
}

fn working<'a, W: Write>(w: &'a W) -> impl Future + 'a {
    PollFn(move |cx| w.poll_close(cx))
}

pub struct PollFn<F: Fn(&mut ())>(F);

impl<F> Future for PollFn<F> where F: Fn(&mut ()) {
    fn poll(&self, cx: &mut ()) {
        (&self.0)(cx)
    }
}
error: non-defining existential type use in defining scope
  --> src/lib.rs:13:51
   |
13 |   fn broken<'a, W: Write>(w: &'a W) -> Close<'a, W> {
   |  ___________________________________________________^
14 | |     PollFn(move |cx| w.poll_close(cx))
15 | | }
   | |_^ lifetime `` is part of concrete type but not used in parameter list of existential type

Removing the cx parameter everywhere makes this work, at a guess it seems like existential types are incorrectly attributing the lifetime of the &mut () that should be hidden in the closure to the concrete type.

@oli-obk
Copy link
Contributor

oli-obk commented Aug 21, 2018

This might be because existential types skip (

) the lifetime hacks (
for lifetime in &path.segments[0].args.as_ref().unwrap().args {
) that impl Trait does

@talchas
Copy link

talchas commented Oct 10, 2018

Even more minified:

existential type X: Clone;

fn bar<F: Fn(&i32) + Clone>(f: F) -> F {
    f
}

fn foo() -> X {
    bar(|x| ())
}

or using more stdlib stuff:

existential type X: Iterator<Item = i32>;

fn temp() -> X {
    vec![1].into_iter().filter(|x| *x > 1)
}

@oli-obk oli-obk added A-closures Area: Closures (`|…| { … }`) A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug. labels Oct 12, 2018
@ExpHP
Copy link
Contributor

ExpHP commented Oct 22, 2018

Also seen in const/static items of type impl Fn(&T): #55272

@matprec
Copy link
Contributor

matprec commented Jan 17, 2019

I've hit this as well, have reduced it further:

#![feature(existential_type)]

existential type Foo<R>: Fn(&R) -> ();

fn bar<R>() -> Foo<R> {
    |r| ()
}

Playground

Changing from Fn(&R) -> () to Fn(R) -> () works

@Lymia
Copy link
Contributor

Lymia commented Mar 27, 2019

Has there been progress in fixing this? I'd be willing to see if I can start work on a PR myself since I've been having issues with this.

@oli-obk
Copy link
Contributor

oli-obk commented Mar 27, 2019

I think it should be enough to add a ReLateBound(_) arm to

ty::ReStatic => region,

@oberien
Copy link
Contributor

oberien commented May 19, 2019

This seems to have been fixed recently, as the example in #53457 (comment) didn't work on nightly 2019-04-11, but now works on the playpen (if you click the link in that comment).

@oli-obk
Copy link
Contributor

oli-obk commented Jun 3, 2019

The fix was in #60799

Centril added a commit to Centril/rust that referenced this issue Jun 4, 2019
Centril added a commit to Centril/rust that referenced this issue Jun 4, 2019
Centril added a commit to Centril/rust that referenced this issue Jun 4, 2019
bors added a commit that referenced this issue Jun 4, 2019
Rollup of 13 pull requests

Successful merges:

 - #61135 (Fix documentation of `Rc::make_mut` regarding `rc::Weak`.)
 - #61404 (miri unsizing: fix projecting into a field of an operand)
 - #61409 (Fix an ICE with a const argument in a trait)
 - #61413 (Re-implement async fn drop order lowering )
 - #61419 (Add an unusual-conversion example to to_uppercase)
 - #61420 (Succinctify splice docs)
 - #61444 (Suggest using `as_ref` on `*const T`)
 - #61446 (On TerminatorKind::DropAndReplace still handle unused_mut correctly)
 - #61485 (azure: retry s3 upload if it fails)
 - #61489 (ci: Reenable step timings on AppVeyor)
 - #61496 (Do not panic in tidy on unbalanced parentheses in cfg's)
 - #61497 (Treat 0 as special value for codegen-units-std)
 - #61499 (Add regression test for existential type ICE #53457)

Failed merges:

r? @ghost
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`) A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants