You are making a recursive call when creating Tree<T>
:
impl<T> Tree<T> {
fn create<F>(value: T, get_children: F) -> Tree<T>
//...
//...
.map(|x| Tree::create(x, |y| get_children(y))) //endless recursive call
I'm confused why it infinitely recursed since I returned an empty
vector in the closure.
This error occurs during compilation and the error says that reached the type-length limit while instantiating...
. This means you are generating an enormously long type.
How does it happen?
When you call Tree::create(x, |y| get_children(y))
you are creating an argument closure which calls an existing closure. This is okay, but when you call it recursively the compiler will not able to detect the type of F
at the most inner call.
Remember get_children
has a type F
where F: Fn(&T) -> Vec<T>
.
When you call Tree::create
for the first time, F
in create<F>
will be inferred like this:
let tree = Tree::create(1, |_| Vec::new());
//inference of F: Fn(&T) -> Vec<T>
After the second call in map(...)
:
Tree::create(x, |y| get_children(y))
//inference of F: Fn(&T) -> Fn(&T) -> Vec<T>
Then it will eventually turn into this:
//inference of F: Fn(&T)-> Fn(&T) -> Fn(&T) -> Vec<T>
//inference of F: Fn(&T)-> ... -> Fn(&T) -> Fn(&T) -> Vec<T>
At the end, the compiler reaches the type-length limit.
Solution with recursion
As an addition to Shepmaster's answer, you can use function pointers:
impl<T> Tree<T> {
fn create(value: T, get_children: fn(&T) -> Vec<T>) -> Tree<T> {
let children = get_children(&value);
Tree {
value,
children: children
.into_iter()
.map(|x| Tree::create(x, get_children))
.collect(),
}
}
}
Solution without recursion
You can fix the issue by sending the function to Vec<Tree<T>>
as get_children
instead of generating in create
, like this:
fn main() {
let inner_tree = Tree::create(1, |_| Vec::new());
let tree = Tree::create(1, move |_| vec![inner_tree]);
println!("{:?}", tree);
}
#[derive(Debug)]
struct Tree<T> {
value: T,
children: Vec<Tree<T>>,
}
impl<T> Tree<T> {
fn create<F>(value: T, get_children: F) -> Tree<T>
where
F: FnOnce(&T) -> Vec<Tree<T>>,
{
let children = get_children(&value);
Tree { value, children }
}
}
Please notice that I changed the function parameter's type from Fn
to FnOnce
. It is needed to move ownership of inner trees into a closure. It is going to be called once so it can consume the variable.