Using an array with `Into` trait for enum of different variants

Someone from reddit suggested using impl Into<JsValue> to not have to use .into() for every argument. I spend some time experimenting and I can't figure it out. So far I only managed to use impl Into<JsValue> when all arguments are of the same type.

The code in question:

pub enum JsValue { Str(String), Number(usize), }
impl From<usize> for JsValue { fn from(n: usize) -> Self { Self::Number(n) } }
impl From<&str> for JsValue { fn from(s: &str) -> Self { Self::Str(s.to_owned()) } }

fn invoke(_params: &[JsValue]) {}

fn main() {
    invoke(&["string".into(), 0.into()]);
}

Yes, impl in argument position always refers to a single concrete type. Think about it like this: You need to create an array before calling the function. An array requires all it's members to have the same size for indexing to work.

Yes, impl in argument position always refers to a single concrete type. Think about it like this: You need to create an array before calling the function. An array requires all it's members to have the same size for indexing to work.

Thanks. How does .into() differs from this requirement? As I'm guessing each argument has different size

When you have ["string".into(), 0.into()], the array you construct is of type [JsValue; 2]. The first element is "string".into(), which, if you follow the definition, is JsValue::Str("string".to_owned()). Same for the 0. Each element is converted to a JsValue, and then an array is made out of them.

The code is equivalent to writing this: [JsValue::String("string".to_owned()), JsValue::Number(0)]. Each element is a JsValue so it compiles.

The two calls of into() look the same, but they refer to different methods.

I can think one way to go around this using a simple macro:

invoke!(&["string", 0]);

that transforms into:

invoke!(&[JsValue::Str("string"), JsValue::Number(0)]);

Suggestions or other ideas are welcome!

Yes, a macro could help here. It would have to expand to this because it can't expect the type but yeah,

invoke!(&[JsValue::from("string"), JsValue::from(0)]);