Nested dyn Trait

How would I implement function get_b() that returns parametrised trait with trait? I.e I'd like to have multiple implementations over B parametrised by A that would be dynamically resolved.

trait A {
    fn a(&self);
}

trait B<T: A> {
    fn b(&self) -> T;
}

struct AA;
impl A for AA {
    fn a(&self) {
        print!("a for aa");
    }
}
struct BB;
impl B<AA> for BB {
    fn b(&self) -> AA {
        AA{}
    }
}

fn get_a() -> Box<dyn A> {
    Box::new(AA{})
}

fn get_b() -> Box<dyn B<dyn A>> {
    Box::new(BB{})
}

The error I get is:

    |     ^^^^^^^^^^^^^^ the trait `B<(dyn A + 'static)>` is not implemented for `BB`

Given the signature of B::b (you can't return a dynamically sized type T: A + ?Sized and dyn A is dynamically sized), I think your best bet would be to add another box around the inner dyn A:

trait A {
    fn a(&self);
}

trait B<T: A> {
    fn b(&self) -> T;
}

struct AA;

impl A for AA {
    fn a(&self) {
        print!("a for aa");
    }
}

impl A for Box<dyn A> {
    fn a(&self) {
        (**self).a()
    }
}

struct BB;

impl B<AA> for BB {
    fn b(&self) -> AA {
        AA {}
    }
}

impl B<Box<dyn A>> for BB {
    fn b(&self) -> Box<dyn A> {
        Box::new(AA {})
    }
}

fn get_a() -> Box<dyn A> {
    Box::new(AA {})
}

fn get_b() -> Box<dyn B<Box<dyn A>>> {
    Box::new(BB {})
}

fn main() {
    let b = get_b();
    b.b().a();
}

Playground.

3 Likes

(This section is basically a repeat of what @jofas said).

In this example, the parameter of B must be Sized (which is a default bound in that position, and also required because you return T by value from B::b). So T can't resolve to dyn A + '_.

It could resolve to Box<dyn A + '_>... if Box<dyn A + '_> implemented A. This isn't automatic: you have to supply the implementation.


(This part is new.)

Next, the only implementor of B<_> in your OP is B<AA> for BB. If you want a Box<dyn B<Box<dyn A>>>, you have to have an implementation of B<Box<dyn A>> somewhere.

Here's a playground with both these pieces.

I'm not sure if it actually does what you want it to do or not, though.


You may have some misconceptions around dyn Trait being a subtype of every implementor of Trait or otherwise representing every implementor of Trait automatically. If so, perhaps this overview will help clarify some things.

2 Likes

Thanks a lot for your replies!