gpt4 book ai didi

rust - 无法移动 dyn 类型的值 <'r> FnOnce(&' r mut [u8]) : the size of dyn for <'r> FnOnce(&' r mut [u8]) cannot be statically determined

转载 作者:行者123 更新时间:2023-12-04 03:31:13 26 4
gpt4 key购买 nike

我正在尝试在线程之间共享一个函数,可以用另一个函数调用它:

fn main() {
let on_virtual_tun_write = std::sync::Arc::new(|f: &dyn FnOnce(&mut [u8]), size: usize|-> std::result::Result<(),()>{
let mut buffer = vec![0; size];
f(buffer.as_mut_slice());
Ok(())
});
}
一旦被调用,它就会使用 f作为参数传递,以检索缓冲区。如您所见,我不打算复制该函数,我只是在有人调用闭包时立即使用它,然后将其丢弃。但是,Rust 认为我想复制它。我该怎么做才能告诉 Rust 我只想使用对函数的引用?我以为 &dyn就足够了。
错误:
error[E0161]: cannot move a value of type dyn for<'r> FnOnce(&'r mut [u8]): the size of dyn for<'r> FnOnce(&'r mut [u8]) cannot be statically determined
--> src/main.rs:4:9
|
4 | f(buffer.as_mut_slice());
| ^

error[E0507]: cannot move out of `*f` which is behind a shared reference
--> src/main.rs:4:9
|
4 | f(buffer.as_mut_slice());
| ^ move occurs because `*f` has type `dyn for<'r> FnOnce(&'r mut [u8])`, which does not implement the `Copy` trait

error: aborting due to 2 previous errors; 1 warning emitted

最佳答案

所以我认为有几个问题共同导致了这个问题。
我将使用一个简化的示例,它生成基本相同的错误消息。

fn main() { 
let ff = |f: &dyn FnOnce()| { f(); };
}
问题的核心是 Rust 正在阻止错误代码,其中 FnOnce使用不止一次。像这样(不编译):
fn main() {
let f = || { }; // Imagine this is a real FnOnce()
let ff = |f: &dyn FnOnce()| { f(); };
ff(&f); // Use the FnOnce in our wrapper
f(); // Use the FnOnce again - should fail to compile.
}
首先 FnOnce()当被调用时会消耗它自己——这就是它如何确保它只能被调用一次。这意味着您需要传递对象,而不是对它的引用 - 否则调用者仍然可以持有引用。 Fn() 不是这种情况和 FnMut() .第一个只使用对 self 的引用,第二个使用对 self 的可变引用。这意味着以下编译正常:
fn main() { 
let ff = |f: &dyn Fn()| { f(); };
let f = || {};
ff(f); // First call is OK
f(); // Second usage is OK - it's a pure function

let ff = |f: &mut dyn FnMut()| { f(); };
let mut i = 0;
let mut f = || { i += 1 };
ff(&mut f); // OK i=1
f(); // OK i=2
println!("i={}", i); // prints 2

}
因此,如果您可以减少对函数类型的限制,使其为 FnFnMut ,那应该会为您解决问题,如果不是……请继续阅读。
您可以传递 FnOnce 的实例(不是引用)到使用 impl 的通用函数.例如
fn ff(f: impl FnOnce()) {
f()
}

fn main() {
// Creating a closure that moves q into it ensures we get a FnOnce
let q=vec![1,2,3];
let f = move || {println!("{}", q.len())};

ff(f); // OK.
// f(); // Compile error with "use of moved value: `f`"
}
这相当于
fn<F> ff(f: F)
where F: FnOnce()
{
f()
}
然而,我们不能以一种可以帮助我们的方式混合泛型和闭包。正在尝试使用 |f: impl FnOnce()|产生错误: error[E0562]: impl Trait not allowed outside of function and inherent method return types .
我认为您可以同时使用 FnOnce 的唯一方法闭包就是把函数装箱并传入。这会将函数的所有权转移到闭包中,所以我们称之为它。例如以下编译:
fn main() {
let ff = |f: Box<dyn FnOnce()>| { f() };
let q=vec![1,2,3];
let f = Box::new(move || {println!("{}", q.len())});
ff(f); // OK
// f(); // Errors with "use of moved value: `f`"
}

关于rust - 无法移动 dyn 类型的值 <'r> FnOnce(&' r mut [u8]) : the size of dyn for <'r> FnOnce(&' r mut [u8]) cannot be statically determined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66774134/

26 4 0