2
votes

When extending traits defined in other crates, there seem to be two ways to default implement a new trait.

The original definition of a trait is

pub trait Trait1 {
    fn f1(&self);
}

In order to extend the functionality of this trait, we define a trait Trait2,

pub trait Trait2 {
    fn f2(&self);
}

Now, because we want the functionality to be available by default, we can implement the following

impl<T> Trait2 for T
where
    T: Trait1,
{
    pub fn f2(&self) {
        self.f1()
    }
}

impl Trait2 for dyn Trait1 {
    pub fn f2(&self) {
        self.f1()
    }
}

What I have observed is that, when mixing with trait objects, both of these implementations are required.

I understand that the impl<T> one is for concrete classes where as other is for dyn objects. Is that correct? Is there any way to share the default implementation here for both of these types? In my scenario, I had to copy and paste the whole implementation with just the change of the first line.

1
it's a bit unclear what you are asking. Could you edit the post to give a more concrete example?Peter Hall
This is a great first question and thanks for adding code. I just tweaked the formatting to match other rust questions, in the hopes that it will be more readable and useful for future users. Welcome to Stack Overflow!trentcl

1 Answers

3
votes

If I understood your question correctly, just add the unsized (?Sized) bound to T:

impl<T> Trait2 for T where T: Trait1 + ?Sized

This implements Trait2 for unsized types (eg. dyn Trait1) that implement Trait1 as well. By default, all type parameters are sized, and hence do not match unsized types.

Playground