问题描述
我遇到了可能是编译器错误.但是,我不太了解这个问题,无法将建议的解决方案移植到我自己的代码中.这是我的代码的精简版:
I'm running into what is potentially a compiler bug. However, I don't understand the issue well enough to port the proposed solution to my own code. Here's a stripped-down version of my code:
struct Node {
pub children: Vec<Node>,
}
fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
F: Fn(&Node) -> R,
{
let mut v: Vec<R> = Vec::new();
v.push(f(n));
v.extend(n.children.iter().flat_map(|child| map_nodes(&f, &child)));
v
}
fn main() {
let node = Node {
children: vec![Node { children: vec![] }, Node { children: vec![] }],
};
println!("Node lengths: {:?}", map_nodes(|n| n.children.len(), &node));
}
特别是这段代码的错误是:
Specifically the error for this code is:
error[E0275]: overflow evaluating the requirement `[closure@src/main.rs:22:46: 22:66]: std::ops::Fn<(&Node,)>`
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `std::ops::Fn<(&Node,)>` for `&[closure@src/main.rs:22:46: 22:66]`
= note: required because of the requirements on the impl of `std::ops::Fn<(&Node,)>` for `&&[closure@src/main.rs:22:46: 22:66]`
# ... this continues for many lines ...
推荐答案
问题是独特的闭包类型之间的不兼容(我将展示如何解决),编译 Rust 时如何实例化泛型,以及递归使用闭包.
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,
每次递归调用都会实例化这个函数的一个新版本,并为 F
插入一个新类型.在这种情况下,map_nodes
接收 F
并传递 &F
,并创建无限系列的新 map_nodes代码> 需要编译的专业化.
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.
您可以做的是通过使用对 Fn
trait 对象的引用来使用具体的闭包类型:
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>
这需要在使用闭包的 lambda 表达式之前插入 &
:map_nodes(&|n| n.children.len(), &node)代码>.
This would require inserting a &
before the lambda expression where the closure is used: map_nodes(&|n| n.children.len(), &node)
.
如果您不想因这种差异而加重公共 API 的负担,那么您可以改为为递归函数使用内部包装器:
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)
}
这篇关于“溢出评估需求"是什么意思?意思是,我该如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!