impl<T> MyStruct<dyn MyTrait<T>> when T has a lifetime parameter

Binders don't switch levels; you don't automatically get an implementation for the higher-ranked type (dyn for<'a> Obj<&'a str>) even if you have an implementation that covers the same set of types in a non-higher-ranked fashion (every dyn Obj<T>). You can see this with something like:

trait Ex {}
impl<R> Ex for dyn HandlerObject<R> {}
impl Ex for dyn for<'a> HandlerObject<&'a str> {}

The implementations are allowed to coexist, even though one of the types is a subtype of the other. [1] To paraphrase Ariel,

dyn for<'a> HandlerObject<&'a str> is not equal to dyn HandlerObject<R> for any R (after all, what would that R be? for<'a> &'a str? That is not a type, and would give us dyn HandlerObject<for<'a> &'a str>, which has the for in the wrong place).

(Now, the example does come with a scary warning pointing to issue 56105 and saying it will become a hard error. But to the best of my knowledge, that's a bald-faced lie; the current direction is to continue accepting them. [2])


Your situation is a little different in that you're trying to induce some sort of equality as a type parameter, versus as an implementer, but I believe it comes down to the same distinction.


  1. The more typical example is fn(T) vs fn(&T) -- aka for<'any> fn(&'any T). ↩︎

  2. Here's another thread with probably way more discussion about it than you care to read; I'm mostly putting a link in here in case I need the breadcrumbs. ↩︎

1 Like