The following Rust code cannot compile:
fn test<F>(f: F)
where for<'a> F: FnOnce(&'a i32),
{
f(&42);
}
fn main() {
test(std::mem::drop);
}
The compiler gives the following error message:
error: implementation of `FnOnce` is not general enough
--> src/lib.rs:8:5
|
8 | test(std::mem::drop);
| ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: `fn(&'2 i32) {std::mem::drop::<&'2 i32>}` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2`
However, if I change the drop function to a closure, like below, then it will compile.
fn main() {
test(|v| {});
}
Therefore, it seems like the closure implements a more general FnOnce, but I cannot see why it is more general.
std::mem::drop takes a generic parameter T. Type parameters cannot be higher-ranked - because a type cannot be. for<'a> &'a i32 is not a valid type, only &'some_specific_lifetime i32 is. Therefore it fails to satisfy the constraint.
The closure however takes known &'a i32, therefore it can be generic over the lifetime.
This more explicit function will also succeed:
fn foo<'a>(_: &'a i32) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With