Why can’t Rust infer the resulting type of Iterator::sum?

The way sum is defined, the return value is open-ended; more than one type can implement the trait Sum<i32>. Here’s an example where different types for a are used, both of which compile:

#[derive(Clone, Copy)]
struct Summer {
    s: isize,
}

impl Summer {
    fn pow(&self, p: isize) {
        println!("pow({})", p);
    }
}

impl std::iter::Sum<i32> for Summer {
    fn sum<I>(iter: I) -> Self
    where
        I: Iterator<Item = i32>,
    {
        let mut result = 0isize;
        for v in iter {
            result += v as isize;
        }
        Summer { s: result }
    }
}

fn main() {
    let a1: i32 = (1i32..10).sum();
    let a2: Summer = (1i32..10).sum();
    let b1 = a1.pow(2);
    let b2 = a2.pow(2);
}

Playground

Since both result types are possible, the type cannot be inferred and must be explicitly specified, either by a turbofish (sum::<X>()) or as the result of the expression (let x: X = ...sum();).

Leave a Comment