phip1611
phip1611

Reputation: 6140

Can't pass an array to the From trait with a slice of arbitrary length

I'm trying to implement From<&[&str]> for one of my types. It should consume an arbitrary length of lines (only known during runtime) and fetches data from the lines. The compiler complains about that &[&str; 2] is not &[&str], i.e. it can't convert a fixed-size slice to one with arbitrary length. The exact message is: the trait 'From<&[&str; 2]>' is not implemented for 'LineEater'

This is my attempt:

fn main() {
    let data = ["foo", "bar"];
    
    // works
    foo(&data);

    // doesn't work
    LineEater::from(&data);

    // also doesn't work
    let data: &[&str] = data.into();
    LineEater::from(&data);
}

struct LineEater;
impl From<&[&str]> for LineEater {
    fn from(_lines: &[&str]) -> Self {
        todo!()
    }
}

fn foo(_slice: &[&str]) {}

Playground

It's confusing that this works with the call of foo() but not the call of from. In the first case Rust can "cast" the [&str; 2] to &[&str] but not in the latter. Why is this so and how can I fix it?

I'm working with Rust 1.55-nightly

Upvotes: 3

Views: 264

Answers (2)

Elias Holzmann
Elias Holzmann

Reputation: 3639

You can use the range operator:

fn main() {
    let data = ["foo", "bar"];
    LineEater::from(&data[..]);
}

struct LineEater;
impl From<&[&str]> for LineEater {
    fn from(_lines: &[&str]) -> Self {
        todo!()
    }
}

Playground link

Or you can use the fully qualified syntax to tell Rust that you want to use the From implementation for &[&str]:

fn main() {
    let data = ["foo", "bar"];
    <LineEater as From<&[&str]>>::from(&data);
}

struct LineEater;
impl From<&[&str]> for LineEater {
    fn from(_lines: &[&str]) -> Self {
        todo!()
    }
}

Playground link

Upvotes: 5

Netwave
Netwave

Reputation: 42678

You need to coerce your array into an slice:

let data: &[&str] = &["foo", "bar"];

Playground

Check out also the first example in the slice documentation

Upvotes: 1

Related Questions