Reputation: 2127
pub struct S{
a: u32
}
fn main() {
let ve = vec![S{a: 1}, S{a: 2}];
ve.iter().filter(filter_function);
}
fn filter_function(s: &S) -> bool {
todo!()
}
Gives
error[E0631]: type mismatch in function arguments
--> src/main.rs:6:22
|
6 | ve.iter().filter(filter_function);
| ------ ^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r &S) -> _`
| |
| required by a bound introduced by this call
...
9 | fn filter_function(s: &S) -> bool {
| --------------------------------- found signature of `for<'r> fn(&'r S) -> _`
|
note: required by a bound in `filter`
And I have no idea why. The signatures are the same. What is wrong?
Upvotes: 0
Views: 815
Reputation: 70267
The signatures aren't quite the same. The expected type is a function which takes a &'r &S
, while your function takes a &'r S
. One has an extra layer of indirection.
You need a function that takes a double reference and calls filter_function
with a single reference. We can do that with an explicit dereference.
ve.iter().filter(|x| filter_function(*x));
However, generally, Rust is pretty good at sorting out these kinds of dereferencing problems in lambdas, so we can simply write
ve.iter().filter(|x| filter_function(x));
and Rust is smart enough to handle the double reference for us.
It's worth mentioning that there should be no performance hit for the extra lambda. filter
takes a generic argument, which means it'll be statically dispatched and hence will be very easy for an optimizer to inline. So the performance should be equivalent to having a top-level function.
Upvotes: 2