为什么这会变成堆栈溢出?
Why does this turn into a stack overflow?
因堆栈溢出而失败的简单测试用例:
// trait to say FnMut has a clone_box method
pub trait ClonableFnMut<A>: FnMut(A) {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static>;
}
// overridden .clone() for Box<ClonableFnMut> that calls .clone_box on f
impl<A: 'static> Clone for Box<dyn ClonableFnMut<A> + Send + 'static> {
fn clone(&self) -> Self {
self.clone_box()
}
}
// .clone_box() on FnMut clones itself and wraps itself in a new Box
impl<A, F: FnMut(A) + Clone + Send + 'static> ClonableFnMut<A> for F {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static> {
Box::new(self.clone())
}
}
fn main() {
let mut f: Box<dyn ClonableFnMut<u8> + Send + 'static> = Box::new(|_x|{});
println!("{:?}", f(3));
println!("{:?}", f.clone()(4));
}
理论上:
- 在
Box<ClonableFnMut>
上致电 .clone()
。
- 自定义实现在内部
FnMut
上调用 .clone_box()
。
- 内部
FnMut
现在可以调用 .clone()
自身,因为它被标记为克隆。
.clone_box()
returns 这克隆了 FnMut
(自己)在一个新的 Box
但实际上:
- 在
Box<ClonableFnMut>
上手动调用 .clone()
。
- 在内部
Box<FnMut>
调用 .clone_box()
。
- 调用
self.clone()
,这似乎意味着 self = box
。
- 自定义
Box<FnMut>
clone()
再次调用,从第 1 步开始。
发生第 4 步的真正原因是什么?
实际发生的事情略有不同:
- 有人在
Box
打电话给 clone
...
- ...在 上调用
clone_box
相同的 Box
...
- ...再次在 上调用
clone
相同的 Box
,关闭循环。
发生这种情况是因为 Clone
的实现只调用了 self.clone_box()
,但 clone_box
是 ClonableFnMut
特征的一个方法。由于一揽子实施,此特征特别在 Box<dyn ClonableFnMut<A> + Send + 'static>
上实施,Box 本身满足 F: FnMut(A) + Clone + Send + 'static
的要求。
为避免这种情况,您需要强制 Clone
实现为 Box
的内容而不是 Box
本身调用 clone_box
方法。有两种风格略有不同的明显方式:
因堆栈溢出而失败的简单测试用例:
// trait to say FnMut has a clone_box method
pub trait ClonableFnMut<A>: FnMut(A) {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static>;
}
// overridden .clone() for Box<ClonableFnMut> that calls .clone_box on f
impl<A: 'static> Clone for Box<dyn ClonableFnMut<A> + Send + 'static> {
fn clone(&self) -> Self {
self.clone_box()
}
}
// .clone_box() on FnMut clones itself and wraps itself in a new Box
impl<A, F: FnMut(A) + Clone + Send + 'static> ClonableFnMut<A> for F {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static> {
Box::new(self.clone())
}
}
fn main() {
let mut f: Box<dyn ClonableFnMut<u8> + Send + 'static> = Box::new(|_x|{});
println!("{:?}", f(3));
println!("{:?}", f.clone()(4));
}
理论上:
- 在
Box<ClonableFnMut>
上致电.clone()
。 - 自定义实现在内部
FnMut
上调用.clone_box()
。 - 内部
FnMut
现在可以调用.clone()
自身,因为它被标记为克隆。 .clone_box()
returns 这克隆了FnMut
(自己)在一个新的 Box
但实际上:
- 在
Box<ClonableFnMut>
上手动调用.clone()
。 - 在内部
Box<FnMut>
调用.clone_box()
。 - 调用
self.clone()
,这似乎意味着self = box
。 - 自定义
Box<FnMut>
clone()
再次调用,从第 1 步开始。
发生第 4 步的真正原因是什么?
实际发生的事情略有不同:
- 有人在
Box
打电话给clone
... - ...在 上调用
clone_box
相同的Box
... - ...再次在 上调用
clone
相同的Box
,关闭循环。
发生这种情况是因为 Clone
的实现只调用了 self.clone_box()
,但 clone_box
是 ClonableFnMut
特征的一个方法。由于一揽子实施,此特征特别在 Box<dyn ClonableFnMut<A> + Send + 'static>
上实施,Box 本身满足 F: FnMut(A) + Clone + Send + 'static
的要求。
为避免这种情况,您需要强制 Clone
实现为 Box
的内容而不是 Box
本身调用 clone_box
方法。有两种风格略有不同的明显方式: