rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.92k stars 12.68k forks source link

Can't return impl trait inside a type when using HRTBs #67262

Open samsartor opened 4 years ago

samsartor commented 4 years ago

This code fails to compile:

struct Wrapper<T>(T);

fn allowed() -> impl for<'a> Fn(&'a u32) -> &'a u32 {
    |x: &u32| x
}

fn not_allowed() -> Wrapper<impl for<'a> Fn(&'a u32) -> &'a u32> {
    Wrapper(|x: &u32| x)
}

The message is:

error[E0271]: type mismatch resolving `for<'a> <[closure@src/lib.rs:8:13: 8:24] as std::ops::FnOnce<(&'a u32,)>>::Output == &'a u32`
 --> src/lib.rs:7:29
  |
7 | fn not_allowed() -> Wrapper<impl for<'a> Fn(&'a u32) -> &'a u32> {
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime
  |
  = note: the return type of a function must have a statically known size

I think this may be related to #54729 but it isn't quite clear. Certainly the workaround mentioned there does not work in this case.

Centril commented 4 years ago

cc @nikomatsakis @matthewjasper @lqd

Ekleog commented 4 years ago

Seeing as it's been a while since the last activity on this and I just hit it, I'm just allowing myself to say this is still an issue :)

Here is a playground link if it can help reproducing with the latest nightly for future people who might come in here without having hit the issue themselves.

Dylan-DPC commented 1 year ago

Current error:

error: lifetime may not live long enough
 --> src/lib.rs:8:23
  |
8 |     Wrapper(|x: &u32| x)
  |                 -   - ^ returning this value requires that `'1` must outlive `'2`
  |                 |   |
  |                 |   return type of closure is &'2 u32
  |                 let's call the lifetime of this reference `'1`

error: higher-ranked lifetime error
 --> src/lib.rs:8:5
  |
8 |     Wrapper(|x: &u32| x)
  |     ^^^^^^^^^^^^^^^^^^^^
fmease commented 4 weeks ago

"Fixed"[^1] by feature https://github.com/rust-lang/rust/labels/F-closure_lifetime_binder:

#![feature(closure_lifetime_binder)]

struct Wrapper<T>(T);

fn allowed() -> impl for<'a> Fn(&'a u32) -> &'a u32 {
    |x: &u32| x
}

fn not_allowed() -> Wrapper<impl for<'a> Fn(&'a u32) -> &'a u32> {
    Wrapper(for<'a> |x: &'a u32| -> &'a u32 { x })
}

[^1]: Or rather, "workaround". Though we will likely never infer a higher-ranked lifetime for the closure in this case (see closure_lifetime_binder's RFC / tracking issue).