7

In rust I would like to have a vec containing items which implement 2 traits. However when I try to implement it like so, I get the error only auto traits can be used as additional traits in a trait object:

let mut v : Vec<Box<dyn MyTrait + std::fmt::Display>> = Vec::new();

FairPlay, I read the error message in full and defined a Trait which combines the two:

pub trait FormattableDoer: std::fmt::Display + MyTrait{}

The have a Vec of Boxes to that:

let mut v: Vec<Box<dyn FormattableDoer>> = Vec::new();

However the compiler can't seem to detect that my struct has implemented those things separately and I get the error the trait bound MyStruct: FormattableDoer is not satisfied.

I read about using a trait alias, but that's not in stable so I'd rather not use it.

Is this possible in rust? It seems like a common thing to want to do and I'm surprised that the answer isn't simple (or maybe it is and I have missed it!). I'm also thinking that maybe I have approached the problem all wrong and I'm attempting to do something in an 'non rusty' way. If that's the case, what is the preferred way of having a vector of things which are displayable and have some other trait?

Playground with a MWE and a use case.

Herohtar
  • 5,347
  • 4
  • 31
  • 41
geeks_kick
  • 151
  • 7

2 Answers2

8

You're almost there. You need a marker trait that implements both parents, as you've already done

pub trait FormattableDoer: std::fmt::Display + MyTrait {}

Then you need a blanket implementation which takes those two traits to your new trait.

impl<T: std::fmt::Display + MyTrait> FormattableDoer for T {}

Now everything that implements std::fmt::Display and MyTrait will implement FormattableDoer automatically, and since FormattableDoer is a single trait, it can be used as a trait object.

Then just use Box<dyn FormattableDoer> like you've already tried.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
3

You still need to implement FormattableDoer for your struct. In the playground you posted, you're not doing that. Simply add

impl FormattableDoer for MyStruct {}

and you should be all done.

No user-defined traits are auto-implemented, even if they contain no methods or associated types.

JMAA
  • 1,730
  • 13
  • 24