I am implementing a tree data structure. My idea to do this is to have a struct Tree
that have children:SomeMapType<Tree>
field to keep track of its children nodes, where SomeMapType
may be BTreeMap
, HashMap
or something else. So instead, I would like it be polymorphic on the map type I choose to use.
Code as follows:
trait Map {
type Key;
type Value;
fn new() -> Self;
}
struct Tree<Symbol, MapType>
where
MapType: Map<Key = Symbol, Value = Box<Self>>,
{
children: MapType,
}
impl<Symbol, MapType> Tree<Symbol, MapType>
where
MapType: Map<Key = Symbol, Value = Box<Self>>,
{
fn new() -> Self {
Self {
children: Map::new(),
}
}
}
impl<Key,Value> Map for std::collections::BTreeMap<Key,Value> {
type Key = Key;
type Value = Value;
fn new() -> Self {
Self::new()
}
}
So far, so good. However, when I am to use this data type, e.g., calling the new
function, by instantiating with a specific map, say BTreeMap
, like follows :
fn main() {
let tree = Tree::<u8,std::collections::BTreeMap<u8,_>>::new();
}
it compiles to an error message :
error[E0271]: type mismatch resolving `<BTreeMap<u8, _> as Map>::Value == Box<Tree<u8, BTreeMap<u8, _>>>`
--> src/zips.rs:162:16
|
162 | let tree = Tree::<u8,std::collections::BTreeMap<u8,_>>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, _> as Map>::Value == Box<Tree<u8, BTreeMap<u8, _>>>`
|
note: cyclic type of infinite size
--> src/zips.rs:155:18
|
155 | type Value = Value;
| ^^^^^
note: required by a bound in `Tree`
--> src/zips.rs:136:32
|
134 | struct Tree<Symbol, MapType>
| ---- required by a bound in this struct
135 | where
136 | MapType: Map<Key = Symbol, Value = Box<Self>>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `Tree`
My guess is that there is some trouble for the rust compiler to reason at that location about recursive types. My question is then how to actually achieve putting an interface that masks the implementation (BTreeMap
or HashMap
) details in my case.