Trying to return a sub-trait/additional trait from a trait implementation that expects to return a trait

Hello,

This may be a XY problem question, so please bear with me.

I have a trait (DoProducer) whose function returns trait objects implementing another trait (Do).

I would like an implementer to be able to return a subtrait of Do (DoMore). The compiler complains about the function signatures not matching.

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

I don't strictly need this to be a subtrait. Rather I want to be able to say "this implementation of DoProducer returns something that promises to implement Do and DoMore". How do I express this?

This is a playground for a "non-subtrait" implementation, which runs into the error of not being able to add non-auto traits. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8aa56e452033b6c6b8c27220e6c32693

Alternatively, is there some other way to achieve a similar result?

You can do this by returning an associated type, which lets each implementation of the trait specify its own return type: (Playground)

trait DoProducer {
    type Result: Do + ?Sized;
    fn produce(&self) -> Box<Self::Result>;
}

struct DoProducerImpl {}


impl DoProducer for DoProducerImpl {
    type Result = dyn DoMore;
    fn produce(&self) -> Box<Self::Result> {   // <---- I want to be able to do this
        if false {
            Box::new(A {})
        } else {
            Box::new(B {})
        }
    }
}

For the non-subtrait version, you’ll need to define a trait that’s a subtrait of both, because the dyn Trait system can only add additional traits if they’re markers with no methods:

trait DoAndMore: Do + DoMore {}
impl<T: Do + DoMore> DoAndMore for T {}

Thank you!
I think I was missing the ?Sized relaxation, which was causing errors!
This works perfectly.

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.