Why can't std::iter::Map<I, F> be returned as Iterator<Item = I>?

Viewed 454

I want make the mapping portion of this line into a function:

let i: Vec<u32> = (0..=5).map(|x| x * 2).collect();

I wrote this code which I assumed would be a drop-in for what I removed from the original code:

let j: Vec<u32> = process(0..=5).collect();
fn process<I>(src: I) -> I
where
    I: Iterator<Item = u32>,
{
    src.map(|x| x * 2)
}

I get this compile time error:

error[E0308]: mismatched types
 --> src/lib.rs:5:5
  |
1 | fn process<I>(src: I) -> I
  |            -             - expected `I` because of return type
  |            |
  |            this type parameter
...
5 |     src.map(|x| x * 2)
  |     ^^^^^^^^^^^^^^^^^^ expected type parameter `I`, found struct `std::iter::Map`
  |
  = note: expected type parameter `I`
                     found struct `std::iter::Map<I, [closure@src/lib.rs:5:13: 5:22]>`

Playground

Since std::iter::Map<u32, u32> implements the Iterator trait, shouldn't it be able to be returned as Iterator<Item = u32>?

I was able to get it working with the following:

fn process<I>(src: I) -> std::iter::Map<I, Box<dyn Fn(u32) -> u32>>
where
    I: Iterator<Item = u32>,
{
    src.map(Box::new(|x| x * 2))
}

This involves wrapping the closure in a Box. Is there a better or less verbose way to do this that matches the inline function?

0 Answers
Related