Let’s say I have a struct like:
struct Foo {
foo: Box<dyn ToString>,
}
Unlike auto-traits like Copy
, which are opt-in, I can’t add #[derive(Send)
to my struct to ask the compiler to opt-in and ensure Send
is implemented by my structure.
What are my options to ensure my type implements for example Send
?
You can statically assert it is Send
by assigning the result of a function to a constant item, the same way you do it with constant 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
That way you don’t depend on tests being built/run.
This question have been raise on the user forum on Rust. The conclusion is there is not really a good way to do this. It’s a weakness of auto-trait like Send
that are not opt-in like Copy
.
A simply way is to use a generic that require the auto-trait, and try to use your type with it:
#[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
It’s far from perfect but at least it will ensure your type is Send if you are doing public API.
Another way would be to use a IsSend
trait:
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
|
But this will add noise in the doc.
1