Open cramertj opened 6 years ago
I believe this is the same issue as https://github.com/rust-lang/rust/issues/41078.
@Mark-Simulacrum I'm not sure this is a proper duplicate-- when I've hit that other issue, I've always been able to get it to go away by explicitly writing out the signature of the closure types. I can't do that here-- you'll notice that the type of the closure is specified manually, yet it still fails.
cc @nikomatsakis
I'm going to reopen this, as I think it at least needs further investigation in order to determine if it is the same as #41076 (which I doubt).
cc @eddyb @nikomatsakis, this is a pretty persistent and important issue for async/await work. It might be most expedient to address it by adding AsyncFn
/AsyncFnMut
/AsyncFnOnce
unstable traits -- does that seem plausible?
@nikomatsakis Looks like this works fine if the bound in take_fn_lt
is replaced with FnOnce(&u8) -> &u8
, which means that either the "closure signature deduction" hack is kicking in there and making it work (unlike FnLt
, which doesn't get the deduction) or going through trait selection imposes additional constraints.
@aturon Not entirely opposed to AsyncFn*
- if unstable, they're easy to add, but I worry that blanket impls won't cut it (as they don't in this issue). And trait aliases aren't implemented yet AFAIK.
Triage: Rust 1.74 gives more details on why it rejects this code. Playground link. It assigns different lifetimes to the closure input and output, contrary to usual elision rules:
error: lifetime may not live long enough
--> src/main.rs:31:34
|
31 | take_fn_lt(|x: &u8| -> &u8 { x }); // Doesn't work
| - - ^ returning this value requires that `'1` must outlive `'2`
| | |
| | let's call the lifetime of this reference `'2`
| let's call the lifetime of this reference `'1`
In the following code, identical impls for a concrete type, a
fn
type, and a closure exist yet the only the closure fails to meet the higher-ranked bound:The error is this:
Edit: the closure can be made to work through coercion to a
fn
pointer (which is unsurprising, since it's then the same asfoo
).take_fn_lt({ |x: &u8| -> &u8 { x } } as fn(&u8) -> &u8);
compiles.