【发布时间】:2021-12-04 01:53:12
【问题描述】:
fn main() {
let mut x = String::new();
let y = || {
let t = x;
};
let mut ww = Box::new(y);
ww();
}
我希望它运行没有任何错误,因为这个实现存在
impl<Args, F, A> FnOnce<Args> for Box<F, A>
但是我遇到了一些奇怪的错误,我无法理解为什么?
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
--> src/main.rs:22:13
|
22 | let y = || {
| ^^ this closure implements `FnOnce`, not `FnMut`
23 | let t = x;
| - closure is `FnOnce` because it moves the variable `x` out of its environment
...
26 | ww();
| ---- the requirement to implement `FnMut` derives from here
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> src/main.rs:22:13
|
22 | let y = || {
| ^^ this closure implements `FnOnce`, not `Fn`
23 | let t = x;
| - closure is `FnOnce` because it moves the variable `x` out of its environment
...
26 | ww();
| ---- the requirement to implement `Fn` derives from here
【问题讨论】:
-
我不会多次运行它。我只希望它像
FnOnce闭包一样运行一次。这只是我试图更好地理解 Fn* 特征的一个例子。 -
哼...你是对的。我不知道为什么它没有自动解决。一种解决方法是取消对自己的引用:
(*ww)(); -
嗯。如果你给
ww一个明确的FnOnce类型,它就会编译:let mut ww: Box<dyn FnOnce()> = Box::new(y)。 -
@JohnKugelman 不过,这会改变语义,因为现在您正在通过 trait 对象的 vtable 调用闭包。我并不是说 OP 不想要这样 - 特征对象动态分派通常是 原因 为什么要装箱 - 只是指出这不是一回事。
(*ww)()是调用问题中创建的闭包的方式,但这是一个很好的问题,为什么ww()不仅可以工作,就像闭包没有装箱时那样。
标签: rust