3

If I have a Vec<T> I can't convert it into Vec<U> directly using .into() even if I can convert T into U using .into(). For example this code does not compile:

use std::convert::From;

struct A {
    x: i32,
}

struct B {
    y: u64,
}

impl From<A> for B {
    fn from(a: A) -> Self {
        Self {
            y: a.x as u64,
        }
    }
}

fn main() {
    let avec: Vec<A> = vec![A{x: 1}, A{x: 2}];
    let bvec: Vec<B> = avec.into(); // Error!
}

I feel like it should be possible to have a blanket impl something like this:

impl<T, U> From<Vec<T>> for Vec<U> where T: From<U> {
    fn from(t: Vec<T>) -> Self {
        t.into_iter().map(Into::into).collect()
    }
}

And similarly for the other collections. Is there a reason this was not done? It would save a lot of tedious code when you want to convert, say a HashMap<String, Vec<Vec<u32>>> to a HashMap<String, Vec<Vec<u64>>>.

Timmmm
  • 88,195
  • 71
  • 364
  • 509

1 Answers1

6

The issue (currently) with having a blanket implementation for converting containers, is that it conflicts with the existing blanket implementation impl From<T> for T.

To be able to get around that, it would in short require specialization (Issue #31844).

// This:
impl<T, U> From<Vec<T>> for Vec<U> where T: From<U>

// Would conflicts with this:
impl<T> From<T> for T

The same question was discussed on the Rust forum not long ago:

vallentin
  • 23,478
  • 6
  • 59
  • 81