Struggling with generics traits

Hey there,
I spent the last couple of weeks reading the Book and after that, I started making some simple exercises, right now I'm stuck with a problem that involves Traits.
For this exercise I want to create a Farm generic trait and the data type bound must be another trait (with fantasy I called it Animal).
I defined the traits as follows:

use anyhow::Result;

pub trait Animal {
    fn animal_type() -> String;
}

pub trait Farm<T> where T: Animal {
    fn add_animal(&self, animal: T) -> Result<()>;
    fn remove_animal(&self, animal: T) -> Result<()>;
    fn merge_farm(self, farm: dyn Farm<T>) -> dyn Farm<T>;
}

The first two functions are easy to implement, I will just need to mutate the internal HashMap to add or remove animals.
But I don't know how to implement the merge_farm function. Well I know the logic, add animals from both farms into a new one but how can I create the farm struct and return it?
And second question: why the compiler is telling me to use the keyword dyn in the second parameter and in the type to return?

This type seems really confused to me. You see, the dyn keyword is only used to specify you want to use a trait object i.e. dynamic dispatch. But that only works with traits.
Assuming Farm<T> is indeed a type, the suggestion makes no sense. Even if the type was a dynamically-sized type (DST), I wouldn't expect a suggestion to add the dyn keyword.

Can you post the definition of the type?

It seems to be a trait, based on the code OP posted.

@fbrv, as for your question, you probably want

fn merge_farm<F, G>(self, farm: F) -> G
    where
        F: Farm<T>,
        G: Farm<T>;

or some variant thereof, e.g.:

fn merge_farm<F, G>(self, farm: F) -> Self
    where
        F: Farm<T>;

both of which do use generics. Using dynamic dispatch (dyn Trait) is the exception, and not the rule, in Rust.

1 Like

Wouldn't

fn merge_farm(self, farm: Self) -> Self;

be enough here ?

I don't know; the first case is strictly more general, as it allows merging non-Self-typed values as well.

1 Like

dyn Trait can't exist on its own. It's never possible to pass, store or return such type.

You can only have it hidden behind a pointer-based type, like Box<dyn Trait> or &dyn Trait.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.