Implementing a trait over a type A or Box<A>

I have a trait like this:

trait Acceptor<B> {
    fn accept(&mut self) -> B;
}

Now, it turns out that in a lot of places my code needs to use a
implementation of Acceptor that has to be instantiated late. So,
I have lots of code like this

struct Blah {
    ac: Option<SomeAcceptor<Class>>
}

impl Blah {
    fn method(&mut self) {
        if let Some(ac) = self.ac {
            ac.accept()
        }
    }
}

Now this got a bit tiresome, so I thought to implement Acceptor for Option.

impl<A, B> Acceptor<B> for Option<A>
where
    A: Acceptor<B>,
{
    fn accept(&mut self) -> B {
        match self {
            Some(ac) => todo!(),
            None => todo!(),
        }
    }
}

Now, I can write my method as:

struct Blah {
    ac: Option<SomeAcceptor<Class>>
}

impl Blah {
    fn method(&mut self) {
       ac.accept()
    }
}

This seems to work, but it fails in one instance because I have

struct Foo {
    ac: Option<Box<SomeAcceptor<Class>>
}

I need the Box to avoid a recursive data structure. So, I thought, I
need to implement Acceptor not just for Option<A> where A:Acceptor, but also anything that deferences to an acceptor:

use std::ops::Deref;

impl<A, B> Acceptor<B> for Option<A>
where
    A: Deref<Target = Acceptor<B>>,
{
}

But this tells me that I have to use dyn, which I presume means that
I will get dynamic dispatch for all my calls to Option<B> including
the non Boxed ones.

Am I right? Is there something better to get this working?

Instead of Target = Acceptor<B>, you want Target: Acceptor<B>. You can re-write your impl like this:

impl<A, B> Acceptor<B> for Option<A>
where
    A: Deref, A::Target: Acceptor<B>,

However, you'll still have an error because this provides conflicting impls for types like Option<Box<Foo>>, which could fall under both impls if Box<Foo> and Foo both implement Acceptor.

Instead, you might want to do something like this:

impl<A, B> Acceptor<B> for Box<A>
where
    A: Acceptor<B>,
{
    fn accept(&mut self) -> B {
        (**self).accept()
    }
}

Full example on Playground.

Thanks, I went for the explicit Box implementation which seems to work well.

I am confused about the semantics of Target = Acceptor<B> vs Target: Acceptor<B> though. I am really not clear on the difference between these two.

In one case the parameter has to be a trait object, in the other case it can be any type that implements the trait.

Ah, okay. Thank you!