If I have the following code:
let a = 1;
let f = |n| n == &a;
let _: Vec<_> = (1u64..10).filter(f).collect();
Rust complains greatly that collect
exists for the relevant Filter
struct, but the trait bound FnMut
is not satisfied by the closure.
However, if I inline the closure or annotate its argument type, the code works, such as:
let a = 1;
let _: Vec<_> = (1u64..10).filter(|n| n == &a).collect();
or:
let a = 1;
let f = |n: &u64| n == &a;
let _: Vec<_> = (1u64..10).filter(f).collect();
Why is this? The fact that inlining the closure without annotating the type works is truly bizarre. I would think it was because n
was having its type inferred as u64
instead of &u64
because ranges have some kind of propensity towards getting consumed but I don't know.
I don't know the exact rule, but from what I've observed working with Rust, creating a closure without requiring a specific type always causes the type to be inferred from the information available in the declaration of the closure only — not how the closure value is used later. That is, Rust's type inference stops being “bidirectional” in this case. For example:
let f = |x| x.clone();
f("hello world");
error[E0282]: type annotations needed
--> src/main.rs:11:14
|
11 | let f = |x| x.clone();
| ^ consider giving this closure parameter a type
|
= note: type must be known at this point
This example fails to compile because the compiler does not use the information from the call to f
to decide that x
should be &str
.
In your case, I'm not sure exactly what the problem is.
I'd assume it was a lifetime problem (the parameter lifetime being inferred as the lifetime of the borrowed a
rather than an arbitrary lifetime) but then I would think that |n: &u64|
wouldn't help.
Another hypothesis is that the problem is that the ==
operator is a PartialEq::eq
call in disguise, and it isn't inferring what the Self
type of that call is (since some type other than u64
could implement PartialEq<&u64>
. But then I'd expect to see another “type annotations needed” error, requiring you to narrow down which trait implementation is to be used.
I don't have a precise explanation, but generally you should expect that when you separate a closure's definition from its usage, you are likely to need to add more type annotations.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.