Rust 无法为<;移动dyn类型的值';r>;FnOnce(&;x27;r mut[u8]):用于<';r>;FnOnce(&;x27;r mut[u8])无法静态确定
我试图在线程之间共享一个函数,该函数可以通过另一个函数调用:Rust 无法为<;移动dyn类型的值';r>;FnOnce(&;x27;r mut[u8]):用于<';r>;FnOnce(&;x27;r mut[u8])无法静态确定,rust,Rust,我试图在线程之间共享一个函数,该函数可以通过另一个函数调用: 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_slic
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(())
});
}
所以我认为有几个问题共同导致了这个问题 我将使用一个简化的示例,它生成基本相同的错误消息
fn main() {
let ff = |f: &dyn FnOnce()| { f(); };
}
问题的核心是,生锈是阻止坏代码,因为FnOnce
被多次使用。像这样(不编译):
首先,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
}
因此,如果您可以减少对函数类型的限制,使其成为Fn
或FnMut
,那么应该可以为您解决这个问题,如果不是的话。。。继续读下去
您可以将FnOnce
的实例(而不是引用)传递给使用impl
的通用函数。e、 g
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()
}
Yuu可以将这个示例简化为
fn main(){let ff=|f:&dyn FnOnce()|{f();};}
,并且仍然得到基本相同的错误消息。
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()
}
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`"
}