I'm trying to create a kind of wrapper trait that combines multiples traits and a function that return the associated implementation of the trait. It works well as long as you don't have associated types. I don't know how to refer to the Output type I am aware of how to combine traits : Is there a way to combine multiple traits in order to define a new trait? Is there any way to create a type alias for multiple traits?
But unfortunately, I've not found anything with associated types
Here is a summarized example of where I'm stucked
use std::ops::Add; pub trait Hello { fn hello(&self); } pub trait Goodbye { fn goodbye(&self); } struct Suffix { suffix: String, } pub struct World { content: String, } impl World { fn new(content: String) -> Self { World { content: content } } } impl Hello for World { fn hello(&self) { println!("Hello {}", self.content) } } impl Goodbye for World { fn goodbye(&self) { println!("Goodbye {}", self.content) } } impl Add<Suffix> for World { type Output = World; fn add(self, other: Suffix) -> World { let suffixed: String = self.content + &other.suffix; World::new(suffixed) } } trait HelloGoodbye: Hello + Goodbye {} impl<T> HelloGoodbye for T where T: Hello + Goodbye {} fn get_hello_goodbye() -> Box<dyn HelloGoodbye> { Box::new(World::new("Everyone".to_string())) } trait SuffixableHello: Hello + Add<Suffix, Output = Self> {} impl<T> SuffixableHello for T where T: Hello + Add<Suffix, Output = Self> {} fn get_suffixable_hello() -> Box<dyn SuffixableHello> { Box::new(World::new("Everyone".to_string())) } fn main() { // This works let hello_goodbye = get_hello_goodbye(); hello_goodbye.hello(); hello_goodbye.goodbye(); // This does not work let suffixable_hello = get_suffixable_hello(); suffixable_hello.hello() } I got this compilation error :
49 | fn get_suffixable_hello() -> Box<dyn SuffixableHello> { | ^^^^^^^^^^^^^^^ help: specify the associated type: `SuffixableHello<Output = Type>` What am I supposed to put there ?
What I've try so far :
- Make trait generic
trait SuffixableHello<T>: Hello + Add<Suffix, Output = T> {} impl<T, U> SuffixableHello<T> for T where T: Hello + Add<Suffix, Output = Self> {} And I get
| 49 | fn get_suffixable_hello() -> Box<dyn SuffixableHello<T>> { | ~~~~~~~~~~~~~~~~~~ Where am I supposed to add this T generic ? Does my fucntion need to be generic ?
- Only add Output to implementation
trait SuffixableHello: Hello + Add<Suffix> {} impl<T> SuffixableHello for T where T: Hello + Add<Suffix, Output = T> {} But I get :
the value of the associated type `Output` (from trait `Add`) must be specified This makes sense since Output is not declared in the trait.
- Replacing
WorldbySelfin theimpl Add<Suffix> for World
Am I missing something here ? Thank you
Also, what if we want to return from the get_suffixable_hello() one of two Hello implementations, let's say World and World2 to cite @cadolphs like in this doc https://doc.rust-lang.org/rust-by-example/trait/dyn.html