Hello! I've been working in rust for a decent while, but this is my first time trying to work with generics to this extent, and I've been running into some trouble.
I'm trying to write a generic graph data structure for a cs class. I have a couple structs that look smthg like this:
trait IVertex<E> {
...
}
trait IEdge<V> {
...
}
// `IVertex` and `IEdge` were given by the professor. They're not very idiomatic, but I can't change them
struct Vertex<E> {
edges: Vec<E>,
}
impl<E> Vertex<E> {
fn new(edges: Vec<E>) -> Self {
Vertex { edges }
}
}
impl<E> IVertex<E> for Vertex<E>
where
E: IEdge<Vertex<E>>,
{
...
}
struct Edge<V> {
destination: Weak<RefCell<V>>,
}
impl<V> Edge<V> {
fn new(destination: Weak<RefCell<V>>) -> Self {
Edge { destination }
}
}
impl<V> IEdge<V> for Edge<V>
where
V: IVertex<Edge<V>>,
{
...
}
I'm able to use them generically as inputs into functions like this:
fn some_function<V, E>(vertex1: V)
where
V: IVertex<E>,
E: IEdge<V>,
{
...
}
But whenever I try to actually use them the compiler insists on explicit type annotations indefinitely, making them impossible to instantiate:
fn main() {
let vertex1: Vertex<Edge<Vertex<Edge<...>>>> = Vertex::new(Vec::new());
}
I know this would be possible by removing Edge entirely and just having Vertexs hold references to each other directly, but I can't change the interface.
I've also gotten it to work by changing Vertex and Edge to refer to each other specifically rather than referring to generic V and E, but that's not ideal since it inseparably links them when theoretically every Vertex could be compatible with any IEdge and every Edge could be compatible with any IVertex.
Is it possible to work with circularly referential generics like these?