为什么调用 FnOnce 闭包会被视为 Move?

8

我正在尝试将一个闭包传递给一个函数,然后在函数的作用域内对传入它的某个内容进行修改。根据我目前对Rust的理解,应该像这样:

pub fn call_something(callback: &FnOnce(&mut Vec<i32>)) {
    let mut my_vec = vec![0, 1, 2, 3, 4];
    callback(&mut my_vec);
}

这会导致以下错误:
error[E0161]: cannot move a value of type dyn for<'r> std::ops::FnOnce(&'r mut std::vec::Vec<i32>): the size of dyn for<'r> std::ops::FnOnce(&'r mut std::vec::Vec<i32>) cannot be statically determined
 --> src/lib.rs:3:5
  |
3 |     callback(&mut my_vec);
  |     ^^^^^^^^

error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:3:5
  |
3 |     callback(&mut my_vec);
  |     ^^^^^^^^ cannot move out of borrowed content

为什么调用 FnOnce 是一次性的?这里我错过了什么吗?
1个回答

9

为什么调用 FnOnce 会移动值?

因为这就是使闭包成为 FnOnce 的定义

extern "rust-call" fn call_once(self, args: Args) -> Self::Output
//                              ^^^^

对比一下这个和 FnMut 以及 Fn
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output
//                             ^^^^^^^^^

extern "rust-call" fn call(&self, args: Args) -> Self::Output
//                         ^^^^^

另请参见:


你可能想要

pub fn call_something(callback: impl FnOnce(&mut Vec<i32>))

或者
pub fn call_something<F>(callback: F)
where
    F: FnOnce(&mut Vec<i32>),

这两者是相同的。它们都拥有闭包的所有权,这意味着您可以在调用闭包的过程中使用它并消耗它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接