Can I define a trait whose implementations must be

2019-07-28 03:12发布

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 {}

2条回答
可以哭但决不认输i
2楼-- · 2019-07-28 03:37

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:

  • an auto-trait.
  • from the current crate.

So the following will work (playground):

#![feature(optin_builtin_traits)]

auto trait Scary {}

trait ThreadThing { }
impl !Scary for ThreadThing {}

But it would not work if you were trying to do:

impl !Send for ThreadThing {}

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 marked Send or !Send by the Rust compiler based upon the contents of the implementing struct.

查看更多
甜甜的少女心
3楼-- · 2019-07-28 03:39

No, you can't make !Send a condition of ThreadThing. 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 implementing ThreadThing for it -- in that case, you would make ThreadThing an unsafe 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 are Send don't implement ThreadThing".

If, as is more likely, it's only unsafe to implement Send manually for a type that implements ThreadThing -- in that case, you don't need to do anything, because manually implementing Send is unsafe already. If an implementor of ThreadThing decides to manually implement Send, they take on the burden of guaranteeing not only their own invariants, but also ThreadThing's.

查看更多
登录 后发表回答