Skip to content

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

New issue

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

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

Already on GitHub? # to your account

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
# for free to join this conversation on GitHub. Already have an account? # 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