How to accept both Vec<String> and Vec<str> as function arg in Rust

You can go for full generic, you don't need to force user to use a Vec, better you can take a generic type that implement IntoIterator that you just have to write that Item implement Into<String>, the syntax is somehow strange and logic. You need a second generic type to do it. I call I the type that will be the iterator and T the Item type.

fn foo<S: Into<String>>(string: S) -> String {
    string.into()
}

fn foo_many<I, T>(iter: I) -> Vec<String>
where
    I: IntoIterator<Item = T>,
    T: Into<String>,
{
    iter.into_iter().map(Into::into).collect()
}

fn main() {
    println!("{}", foo(String::from("bar")));
    println!("{}", foo("baz"));

    for string in foo_many(vec!["foo", "bar"]) {
        println!("{}", string);
    }

    for string in foo_many(vec![foo("foo"), foo("baz")]) {
        println!("{}", string);
    }
}

This solve your problem and make your function even more generic.


This doesn't work because your iteration doesn't give you S but &S.

If you want to move the strings out of the vector, you must make it mutable and drain it:

fn foo_many<S: Into<String>>(mut strings: Vec<S>) -> Vec<String> {
    strings.drain(..).map(|s| s.into()).collect()
}

playground