Being generic over traits

#1

Hi,

im building a virtual-document-object-model (vdom) thingy, but the idea behind it is, that it should be as much static as possible, so only the dynamic parts of the vdom should be dynamic. The diffing for the static parts would be just optimized away by the compiler.

So im using something similar to “Zero-Runtime-Cost Mixed List in Rust” to build node attributes (actually it should be a Map<String, String>, but im simplifying it into a list of (String, String)) and child nodes.

Dynamic things are handled by having a special dynamic type for that, like AttrDyn for dynamic attributes, a Vec<N> where N: Node for dynamic lists or enums to switch between different sub-trees.

Having sum enums for that would be really great! And also generic consts to have real static values (im storing the static values as normal values in the tree right now and just assume they never change, so i don’t need to check for changes).


Now the actual question is, how do i make this more generic, i would like to make a framework for that. With a DSL, that allows you to define different node types. Currently i only have two, attributes and (html-) nodes. But i would also like to be able to do a vdom for gtk.

I can only think of two solutions for that:

  1. some sort of higher kinded types, and then doing something like this:
// my framework would generate a trait for each node "group". here it's a gtk widget.
trait Widget {
  // ...
}

// T is a trait constrain, that gets forwarded without being resolved into a type
trait List<trait T> {
    fn visit<V>(&mut self, visitor: &mut V) -> Result<(), V::Err>
    where
        V: Visitor<forward T>;
}

impl<trait T, L1, L2> List<T> for (L1, L2)
where
    L1: List<forward T>,
    L2: List<forward T>,
{
    fn visit<V>(&mut self, visitor: &mut V) -> Result<(), V::Err>
    where
        V: Visitor<forward T>,
    {
        self.0.visit(visitor)?;
        self.1.visit(visitor)
    }
}

// now use `List<Widget>` to store children in a container:
// it's again a generated trait, it's impled for all gtk types that are `Container`s
trait Container {
  fn children(&self) -> &List<Widget>;
}
  1. generate all possible variants “by hand” resulting in ListWidget, ListContainer and so on being generated (that’s what im doing right now in vdom).

is there a better solution for this, that i haven’t thought about yet?

#2

You can’t be generic over traits in Rust. You can use macros to make writing all the cases simpler though.

There is a proposal to allow Rust to be generic over traits, but it isn’t likely that we will see it soon.

4 Likes
#3

This is one of my long-term projects that will eventually make its way into an RFC. This will be developed under WG-Traits eventually but for now its not a focus of either the working group or the language team.

5 Likes
closed #4

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.