Different impls for types of slices and arrays

Consider the following Playground:

It fails due to conflicting impls. Is there a way to achieve this? i.e. specific impls for different types of slices/vecs/arrays?

struct Foo<T>(T);
trait FooImpl {
    fn do_it(&self);
}

impl <T: AsRef<[u8]>> FooImpl for Foo<T> {
    fn do_it(&self) {
        println!("I am a u8!");
    }
}

impl <T: AsRef<[f32]>> FooImpl for Foo<T> {
    fn do_it(&self) {
        println!("I am a f32!");
    }
}

fn main() {
    Foo([42u8]).do_it();
    Foo(&[42u8]).do_it();
    Foo(vec![42u8]).do_it();
    Foo(&vec![42u8]).do_it();
    
    Foo([42.0f32]).do_it();
    Foo(&[42.0f32]).do_it();
    Foo(vec![42.0f32]).do_it();
    Foo(&vec![42.0f32]).do_it();
    
}

Related thread: Impl generic over slices and vectors

You can use @Nemo157’s solution from the thread you linked and do something like this.

2 Likes

Ah - thanks… where I was stuck toying with that was not seeing where PhantomData comes from… didn’t think to add a new(). Much appreciated!

You can still make Foo without using new:

Foo([42u8], PhantomData)

but I like it better with it =)

1 Like

Btw, off-topic but I’m using your BeachMap a lot… it’s great!

Followup question… now, when I try an add a function that accepts a FooImpl like this, it breaks:

fn do_foo<T: FooImpl> (foo:T) {
    foo.do_it();
}

FooImpl is only implemented for Foo, guess it should be like this:

do_foo(Foo::new([42u8]));
1 Like

d’oh - silly mistake… guess I should have breakfast first :wink: thanks!

One more gotcha - if I have arrays that are larger than 32, is this the idiomatic way to get around it?

Foo::new(&[42u8;33][..]).do_it();

It’s the usual way to go about it, you can use this too:

Foo::new([42u8;33].as_ref()).do_it();
1 Like

OK and… I think this is the last question for now… if I want to know something about the data on Foo, from within the function that accepts it as a generic Trait, I’ll need to make accessor methods part of the trait, right?

Example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0d81b66eb11b4135cbacf1b68c3d338e

I’ll need to make accessor methods part of the trait, right?

Yes.

1 Like