What does “Overflow evaluating the requirement” mean and how can I fix it?

The problem is an incompatibility, (which I’ll show how to resolve) between unique closure types, how generics are instantiated when Rust is compiled, and a recursive use of the closure.

fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
    F: Fn(&Node) -> R,

Each recursive call instantiates a new version of this function, with a new type inserted for F. In this case, the map_nodes receives F and passes on &F, and it creates an infinite series of new map_nodes specializations that would need to be compiled.

What you can do instead is use a concrete closure type by using a reference to a Fn trait object:

fn map_nodes<R>(f: &Fn(&Node) -> R, n: &Node) -> Vec<R>

This would require inserting a & before the lambda expression where the closure is used: map_nodes(&|n| n.children.len(), &node).

If you don’t want to burden your public API with this difference, then you can use an internal wrapper for your recursive function instead:

fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
    F: Fn(&Node) -> R,
{
    fn map_nodes_inner<R>(f: &Fn(&Node) -> R, n: &Node) -> Vec<R> {
        let mut v: Vec<R> = Vec::new();
        v.push(f(n));

        v.extend(n.children.iter().flat_map(|child| map_nodes_inner(f, &child)));

        v
    }

    map_nodes_inner(&f, n)
}

Leave a Comment