Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what aspects does Rust closure implement a more general FnOnce trait than a function?

Tags:

rust

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.

like image 301
Zhiyao Avatar asked Oct 23 '25 03:10

Zhiyao


1 Answers

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) {}
like image 94
Chayim Friedman Avatar answered Oct 26 '25 03:10

Chayim Friedman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!