Reputation: 571
I don't understand why Rust fails to infer the type for Vec<_>
in some cases. If I run this
fn main() {
let v = vec![1, 2, 3];
let s = v.iter().sum();
}
I get an error:
error[E0282]: type annotations needed
--> src/main.rs:5:9
|
5 | let s = v.iter().sum();
| ^ consider giving `s` a type
so that I have to modify it to either
fn main() {
let v = vec![1, 2, 3];
let s = v.iter().sum::<i32>();
}
or
fn main() {
let v = vec![1, 2, 3];
let s: i32 = v.iter().sum();
}
Why the type inference fails here? It correctly gets that v
is a Vec<i32>
so if sum
it's on that vector why does it need i32
to be annotated?
Upvotes: 0
Views: 258
Reputation: 10218
To expand on the Chayim Friedman's answer, consider the following code:
use core::iter::Sum;
// here might be some complex state, e.g. a kind of "long arithmetic"
struct Consumer;
impl<'a> Sum<&'a i32> for Consumer {
fn sum<I: Iterator<Item = &'a i32>>(_: I) -> Self {
// here might be some complex logic
Self
}
}
fn main() {
let v = vec![1, 2, 3];
let s: Consumer = v.iter().sum();
}
You can see that the main
function differs from your example only in the type of s
. Therefore, without this type it's potentially ambiguous - note that the Consumer
struct (and, consequently, its implementation) could very well be in another crate, not controlled by you. Therefore, Rust forces you to make an explicit choice, what exactly to sum into.
Upvotes: 4
Reputation: 70900
Iterator::sum()
is generic over its return type. This allows you to e.g. sum an iterator of &i32
s into an i32
, since i32
impls Sum<&i32>
. Because of that, the compiler cannot infer the return type.
Upvotes: 3