我有以下 Rust 代码(rustc 1.75.0),它“强制”发送一个类型:
struct ForceSend<T>(T);
unsafe impl<T> Send for ForceSend<T> {}
pub fn perform<T>(t: T) {
let wrapped = ForceSend(t);
takes_send(move || {
wrapped.0;
});
}
fn takes_send<F: Send>(_: F) {}
Run Code Online (Sandbox Code Playgroud)
我希望这段代码能够编译,因为闭包通过移动捕获单个值wrapped,并且该值是 Send。根据文档:
如果非唯一不可变引用捕获的所有变量都是同步的,并且唯一不可变或可变引用、复制或移动捕获的所有值都是发送,则闭包为发送。
然而,这无法编译,报告关闭不是发送。
为什么这不能编译?谢谢你的帮助!
wrapped.0.0仅移动中的字段wrapped,该字段的类型为 T(非发送)。这通常对于部分移动很有用,您可以移动捕获字段的子集,并将其余字段保持为未移动。
在这种情况下,您必须确保移动整个 对象,例如通过创建将整个对象移动到闭包中的wrapped绑定:Wrapped
struct ForceSend<T>(T);
unsafe impl<T> Send for ForceSend<T> {}
pub fn perform<T>(t: T) {
let wrapped = ForceSend(t);
takes_send(move || {
let w = wrapped;
w.0;
});
}
fn takes_send<F: Send>(_: F) {}
Run Code Online (Sandbox Code Playgroud)
与此无关的一点是,如果T确实不受限制,则此代码可能不健全,并且如果takes_send确实想要跨线程发送内容,则可能会导致 UB。例如,如果从与获取线程不同的线程中释放互斥体/相关的某些操作系统实现,则会发生故障,并且MutexGuard跨线程发送可能会产生这种情况。
顺便说一句,这是一个在更有用的情况下捕获期间部分移动行为的示例:
pub struct Foo(String, String);
pub fn perform(t: Foo) {
takes_closure(move || {
t.0
});
takes_closure(move || {
t.1
});
}
fn takes_closure<F: FnOnce() -> String>(_: F) {}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
71 次 |
| 最近记录: |