Consider the following code:
fn expects_closure(_closure: impl Fn(&i32)) {}
fn passes_closure(closure: impl Fn(&i32)) {
// Why is this hint required? vvvv
let encapsulated_closure = |a /* : &_ */| closure(a);
expects_closure(encapsulated_closure);
}
The code compiles if we add the commented type hint a: &_
. Otherwise, the compiler complains about the following:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/lib.rs:7:5
|
7 | expects_closure(encapsulated_closure);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected trait `for<'a> Fn(&'a i32)`
found trait `Fn(&i32)`
note: this closure does not fulfill the lifetime requirements
--> src/lib.rs:5:32
|
5 | let encapsulated_closure = |a /* : &_ */| closure(a);
| ^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> src/lib.rs:1:35
|
1 | fn expects_closure(_closure: impl Fn(&i32)) {}
| ^^^^^^^^
help: consider specifying the type of the closure parameters
|
5 | let encapsulated_closure = |a: &_| closure(a);
| ~~~~~~~
error: implementation of `FnOnce` is not general enough
--> src/lib.rs:7:5
|
7 | expects_closure(encapsulated_closure);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 i32)` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (lib) due to 2 previous errors
Why do I need to use a type hint here? Why does the compiler assume that without the type hint, the closure parameter a
could have a given specific lifetime, instead of any lifetime?
Is this a shortcoming in the compiler, or is there a deeper reason behind this?