I'd like to define a trait which forces its implementors to under no circumstances be sent to, or shared between, threads. It should suffice to mark the trait as !Send
, but Rust doesn't seem to let me.
Is it possible?
Example (playground):
#![feature(optin_builtin_traits)]
// This is a syntax error
//trait ThreadThing : !Send {}
// This doesn't work either
trait ThreadThing { }
impl !Send for ThreadThing {}
The answer is: yes, you can, under some very specific conditions. Whether you should need to do this is another matter.
You can define a negative trait implementation for another trait if the trait you are negating is:
So the following will work (playground):
But it would not work if you were trying to do:
Or if
Scary
was not an auto-trait.Note however that, in general it should not be necessary to mark a trait
!Send
in this way. The concrete implementations of the trait will be markedSend
or!Send
by the Rust compiler based upon the contents of the implementing struct.No, you can't make
!Send
a condition ofThreadThing
. The compiler just doesn't support that kind of logic.If it would be possible for someone using your crate to make a type that is implicitly
Send
, contains no unsafe code in its implementation anywhere, and make it unsafe just by implementingThreadThing
for it -- in that case, you would makeThreadThing
anunsafe trait
to indicate that there is unsafe code somewhere that relies on an invariant that can't be described in the type system: the invariant "Things that areSend
don't implementThreadThing
".If, as is more likely, it's only unsafe to implement
Send
manually for a type that implementsThreadThing
-- in that case, you don't need to do anything, because manually implementingSend
is unsafe already. If an implementor ofThreadThing
decides to manually implementSend
, they take on the burden of guaranteeing not only their own invariants, but alsoThreadThing
's.