From<T> for Vec<T>

I was just wondering if there is a good reason that impl From<T> for Vec<T> isn't currently implemented in the compiler? Or if it just hasn't been implemented yet? I have a function with a parameter that needs to be a Vec, but it's possible that sometimes we'll only have 1 T so we end up having to wrap it like vec![t] in order to pass it to the function. It would be convenient to be able to do:

fn foo<T: Into<Vec<T>>>(t: T) {
    let t = t.into();
}

// ...

// now both these are valid
foo(some_t);
foo(some_vec_of_t);

I'd be willing to put in a PR for this but I was wondering if there is a legitimate reason that it isn't in the compiler already.

There are very good reasons for why this is not implemented in the compiler, but I think you are asking about the standart library.

You can just use this instead and it will do the same:

foo(vec![some_t]) 

What you don't like about this solution?

1 Like

You could also use a singleton array, foo([some_t]), for converting Into<Vec<T>>.

7 Likes

It's a blanket implemetnation and thus a major breaking change, so the barrier is probably high (people may have already written their own impl From<MyType> for Vec<MyType>s).

9 Likes

Yea that's what we currently do, like I said, it would be convenient to not have to do that at the call site

I don't dislike it, that's what we currently do. The pattern of accepting parameters that implement Into<T> or AsRef<T> instead of just T is a fairly common one and the fact that I can't do it in this particular case just stuck out to me.

One heuristic I've been trying out for "From reasonableness" of late is whether the inverse conversion using TryFrom (or just From, of course) also feels reasonable. That gives me a more concrete way to think about lossless-enough and similar-enough to be worth not having a clearer method name.

I think that in this case, T: TryFrom<Vec<T>> feels pretty weird, which makes me more skeptical about the Vec<T>: From<T>.

But that also gives a way to think about the direction here. The version of that which fits well is Vec<T>: From<[T; 1]> and [T; 1]: TryFrom<Vec<T>>, which both already exist.

So that means that foo([some_t]); will already work, which TBH I find clearer anyway.

(Now, maybe it would be reasonable to have T: From<[T; 1]> and [T;1]: From<T>. But I'm not sure.)

2 Likes

I'm skeptical that people will have actually written that implementation since it breaks the orphan rule.

It doesn't.

1 Like

Ah, you're right, I was trying to do it with another std type instead of my own, sorry

Also, when using a system language, I don’t want to have unwanted allocation. I’m not at all against allocations in general, I’m using String and Vector after all, but against unexpected ones. When calling foo(some_t) I don’t expect to have an allocation just to be able to pass the parameter some_t.

5 Likes