impl<T, U: From<T>> From<Vec<T>> for Vec<U>

Considering that code snippet

struct Newtype(usize);

impl From<usize> for Newtype {
    fn from(item: usize) -> Self {
        Newtype(item)
    }
}

fn main() {
    let us: usize = 0;
    let newtype: Newtype = us.into(); // works

    let vec: Vec<usize> = vec![0, 1, 2];
    let vec_newtype: Vec<Newtype> = vec.into(); // not works
}

Maybe it would be better to have an impl such like

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

In the standard library?

Could it be considered if I'll make a PR like this?

Also I have a question, wouldn't it be useful for all types? To automatically have Into, if all generics do have impl Into? Maybe if Into is unwanted, it could be possible to opt out them with negative impl?

This impl would overlap and thus conflict with the reflexive impl<T> From<T> for T.

But it is allowed to use min_specialization in standard library, isn't it?

item.into_iter().map(U::from).collect() should be optimized out if T == U

1 Like

As far as I know, at the moment, specialization is used in the standard library only for performance optimizations, not to write publicly visible trait implementations that are impossible without specialization.

Also specialization is of limited help here, since not one implementation is more general than the other, but we have two overlapping ones, but both impls contain cases the other one doesn’t.

4 Likes

Yes, I see now. But could it be helped in some other way, because it would be really convenient to have such a feature:

    let vec: Vec<usize> = vec![0, 1, 2];
    let vec_newtype: Vec<Newtype> = vec.into(); 

?

Maybe with More flexible coherence rules that permit overlap · Issue #1053 · rust-lang/rfcs · GitHub (mutually exclusive traits) and to specify that T != U (somehow) it would be possible?

And thank you very much for your answers.

1 Like

You can't specify T != U though.

Can't you just do .into_iter().map(Into::into).collect::<Vec<_>>()? Or maybe write a helper function for it with a short name, like vec_into.

2 Likes

Exactly this.

From impls like this are widely desired -- Option wants an analogous one, for example -- but can't happen yet.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.