Search code examples
genericslinked-listruststatic-dispatch

How can I have static dispatch for a linked list containing different types all implementing a trait?


I have this working code:

struct Layer<'a> {
    parent: Option<Box<Layer<'a>>>,
    value: Box<dyn Renderable + 'a>,
}

I would like to have a version using static dispatch instead:

struct Layer<'a, R: Renderable> {
    parent: Option<&'a Layer<'a, /* ? */>>,
    value: R,
}

The type replacing the question mark implements Renderable, but it's not necessarily R, it could be T: Renderable for example. I would like to avoid any solution using dyn Renderable, to keep the static dispatch.

The type T: Renderable is known at Layer instantiation and won't change.


Solution

  • TL;DR: It is impossible (at least w/o variadic generics*)

    • Right now Layer structure requires 2 generic parameters: R and 'a.

    • Let's imagine we found the right type for /* ? */. Let's name it T0.

    • Then Layer structure will require 3 generic parameters: T0, R and 'a.

    • Then you have to provide one more generic parameter for parent field. Let's name it T1.

    • Then Layer structure will require 4 generic parameters: T1, T0, R and 'a.

    • Then you have to provide one more generic parameter for parent field. Let's name it T2.

    • <...>

    • Then Layer structure will require i+2 generic parameters: Ti, Ti-1, ... T1, T0, R and 'a.
    • Then you have to provide one more generic parameter for parent field. Let's name it Ti+1.
    • Then Layer structure will require i+1+2 generic parameters: Ti+1, Ti, Ti-1, ... T1, T0, R and 'a.
    • <...>

    At the end, you have infinite recursion. Additional generic parameter for parent field have to be defined as a part of Layer structure. That induce introduction of a new generic parameter for Layer. That induce additional generic parameter for parent field.

    To break up recursion, additional generic parameter for parent shouldn't be a part of Layer definition. If a parameter is not a part of Layer definition then we can't calculate Layer size at compile time. The way it may be solved is &dyn or Box.

    *The other possible solution is variadic generics but it looks like we will not have it at least for next few months or even years.