I often want to define recursive data type in Rust. We need some level of indirection to avoid having a type with unbounded size. The classic solution is to use Box
(playground):
enum IntList {
Empty,
Cons(i32, Box<IntList>),
}
The problem I have with this it that it requires that the list own its own tail. This means you can't have space sharing between two lists that share a tail because both want to own it. You could use a borrowed reference (playground):
enum IntList<'a> {
Empty,
Cons(i32, &'a IntList<'a>),
}
But then it's hard to create a list because it's not allowed to own its own tail.
Is there a way to have the list not care whether or not it owns the tail? That way I could have one list own the tail and another list have a reference to that same list as its tail.
My Attempt
My first thought was to use Cow
for this purpose, but I couldn't get it to work. This is what I tried (playground):
#[derive(Clone)]
enum IntList<'a> {
Empty,
Cons(i32, Cow<'a, IntList<'a>),
}
but it fails with error
error[E0275]: overflow evaluating the requirement `IntList<'a>: std::marker::Sized`
--> src/main.rs:8:13
|
8 | Cons(i32, Cow<'a, IntList<'a>>),
| ^^^^^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `std::borrow::ToOwned` for `IntList<'a>`
= note: required because it appears within the type `std::borrow::Cow<'a, IntList<'a>>`
= note: no field of an enum variant may have a dynamically sized type