假设我有一个类似的结构:
struct Foo {
foo: Box<dyn ToString>,
}
与
Copy
这样的自动特征不同,它是选择加入的,我无法将 #[derive(Send)
添加到我的结构中以要求编译器选择加入并确保 Send
由我的结构实现。
我有什么选择可以确保我的类型实现例如
Send
?
您可以通过将函数的结果分配给常量项来静态断言它是
Send
,与常量 assert
s 的操作方式相同:
const fn assert_send<T: Send>() {}
const _: () = assert_send::<Foo>()
error[E0277]: `(dyn ToString + 'static)` cannot be sent between threads safely
--> src/lib.rs:6:29
|
6 | const _: () = assert_send::<Foo>();
| ^^^ `(dyn ToString + 'static)` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `(dyn ToString + 'static)`, which is required by `Foo: Send`
= note: required for `Unique<(dyn ToString + 'static)>` to implement `Send`
note: required because it appears within the type `Box<(dyn ToString + 'static)>`
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:197:12
这样您就不必依赖于构建/运行的测试。
这个问题已在 Rust 的 用户论坛 上提出。结论是没有真正的好方法来做到这一点。这是像
Send
这样的自动特征的弱点,它不像 Copy
那样可以选择加入。
一个简单的方法是使用需要自动特征的泛型,并尝试将您的类型与它一起使用:
#[cfg(test)]
mod tests {
use crate::Foo;
fn test_send<T: Send>() {}
#[test]
fn foo_must_be_send() {
test_send::<Foo>();
}
}
error[E0277]: `(dyn ToString + 'static)` cannot be sent between threads safely
--> src/lib.rs:13:17
|
13 | test_send::<Foo>();
| ^^^ `(dyn ToString + 'static)` cannot be sent between threads safely
它远非完美,但至少它会确保你的类型是发送,如果你正在做公共API。
另一种方法是使用
IsSend
特征:
impl IsSend for Foo {}
trait IsSend: Send {}
error[E0277]: `(dyn ToString + 'static)` cannot be sent between threads safely
--> src/lib.rs:5:17
|
5 | impl IsSend for Foo {}
| ^^^ `(dyn ToString + 'static)` cannot be sent between threads safely
|
但这会增加文档中的噪音。