Description
I ran into a compile error while writing some iterator adapters involving building (types containing) closures in a function returning (types containing) impl for<'a> Fn(&'a)
, which I narrowed down to the following example:
fn const_if_unit(input: bool) -> impl for<'a> FnOnce(&'a ()) {
if input {
|_| ()
} else {
|_| ()
}
}
This function fails to typecheck, seemingly because the return type is inferred to only implement Fn(&())
rather than for <'a> Fn(&'a ())
.
Note that replacing the body with an unconditional |_| ()
instead works as expected, and using functions rather than closures also compiles without errors, see playground for more examples.
I'm on Rust 1.65.0 but the playground shows the same happening in beta and nightly too.
Seems related to #99991 and maybe #98437 (that I could find), but they are about trait bounds in input types rather than return impl
, and here it actually does work as long as the closure is returned unconditionally, though feel free to close as duplicate if it's ultimately the same root issue.
`cargo check` output
error[E0308]: mismatched types
--> repro/src/main.rs:2:19
|
2 | if input {
| ___________________^
3 | | |_| ()
4 | | } else {
| |_____^ one type is more general than the other
|
= note: expected trait `for<'b> FnOnce<(&'b u8,)>`
found trait `FnOnce<(&u8,)>`
error: implementation of `FnOnce` is not general enough
--> repro/src/main.rs:2:19
|
2 | if input {
| ___________________^
3 | | |_| ()
4 | | } else {
| |_____^ implementation of `FnOnce` is not general enough
|
= note: `fn(&'2 u8)` must implement `FnOnce<(&'1 u8,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 u8,)>`, for some specific lifetime `'2`
error: higher-ranked lifetime error
--> repro/src/main.rs:4:12
|
4 | } else {
| ____________^
5 | | |_| ()
6 | | }
| |_____^