apocalypsis
apocalypsis

Reputation: 571

Why rust fails type inference for Vec<_>

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

Answers (2)

Cerberus
Cerberus

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();
}

Playground

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

Chayim Friedman
Chayim Friedman

Reputation: 70900

Iterator::sum() is generic over its return type. This allows you to e.g. sum an iterator of &i32s into an i32, since i32 impls Sum<&i32>. Because of that, the compiler cannot infer the return type.

Upvotes: 3

Related Questions