I want to sort a list of numbers using something along these lines (smallest reproducible example):
fn foo(bar: i32) -> i32 {
bar
}
fn main() {
let comparator = |&a, &b| foo(a).cmp(&foo(b));
let mut baz = vec![5, 2, 3, 8, 0, -6];
baz.sort_by(comparator);
}
However, it fails to compile, and I get this message:
error[E0308]: mismatched types
--> src/main.rs:36:5
|
36 | baz.sort_by(comparator);
| ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected trait `for<'a, 'b> FnMut<(&'a i32, &'b i32)>`
found trait `FnMut<(&i32, &i32)>`
note: this closure does not fulfill the lifetime requirements
--> src/main.rs:34:22
|
34 | let comparator = |&a, &b| foo(a).cmp(&foo(b));
| ^^^^^^^^
note: the lifetime requirement is introduced here
--> ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/slice.rs:260:12
|
260 | F: FnMut(&T, &T) -> Ordering,
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: implementation of `FnOnce` is not general enough
--> src/main.rs:36:5
|
36 | baz.sort_by(comparator);
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 i32, &i32) -> std::cmp::Ordering` must implement `FnOnce<(&'1 i32, &i32)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 i32, &i32)>`, for some specific lifetime `'2`
error: implementation of `FnOnce` is not general enough
--> src/main.rs:36:5
|
36 | baz.sort_by(comparator);
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&i32, &'2 i32) -> std::cmp::Ordering` must implement `FnOnce<(&i32, &'1 i32)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&i32, &'2 i32)>`, for some specific lifetime `'2`
I don't get the error messages, what is the difference between for<'a, 'b> FnMut<(&'a i32, &'b i32)>
and FnMut<(&i32, &i32)>
?
The error message also mentions the FnOnce
trait, and I don't understand why, since the closure should implement FnMut
(and sort_by
requires FnMut
) (or maybe FnOnce
is implemented if FnMut
is implemented ?
But the biggest thing that I don't understand is that, if I don't assign a name to the closure and instead pass it like this: baz.sort_by(|&a, &b| foo(a).cmp(&foo(b)));
, it compiles !?
What is going on, and how can I pass my closure ?