rust-lang / libs-team

The home of the library team
Apache License 2.0
115 stars 18 forks source link

Help wanted: what to do with UnwindSafe and RefUnwindSafe #273

Open m-ou-se opened 11 months ago

m-ou-se commented 11 months ago

It has been suggested many times that UnwindSafe and RefUnwindSafe are more often an annoyance than they are useful, and that it might be time to effectively disable/remove them.

Doing so requires some research and the design of a backwards compatible deprecation path.

To do:

Or, if it turns out to be a bad idea to deprecate these traits:

joboet commented 11 months ago

Actually I wanted to write a blog post about this, but I have been procrastinating that for too long...

I think the two biggest problems are that

  1. being auto-traits, it's incredibly easy to accidentally introduce/delete their implementation.
  2. they do not allow mutation, even when it leaves everything consistent. E.g. a &mut i32 should be UnwindSafe, because i32 does not have any invariants that may be broken.

For me, the ideal design would have used two safe non-auto marker traits, Consistent and RefConsistent (as in database consistency), where Consistent implies/requires RefConsistent. These would be implemented where operations by-value/by-ref cannot break the invariants of the type they are implemented on. So all primitives would be Consistent and RefConsistent, because they do not have invariants. BinaryHeap would implement Consistent (if T implements it), because it guarantees the heap invariants stay intact with every operation (in particular, PeekMut cannot be used to break the ordering invariant). But types that allow breaking the invariants (even temporarily) through their API should not implement them, as if a panic or a leak occurs they are left in an inconsistent state. These traits could then have been used in Mutex and RwLock instead of lock poisoning, and in catch_unwind to require that the closure only holds/references types that are Consistent/RefConsistent.

I doubt that these could be introduced in exactly that fashion, but maybe lint-traits (as in marker traits that warn instead of generating an error if unimplemented) would allow their introduction in a backwards-compatible way.

VorpalBlade commented 11 months ago

These traits could then have been used in Mutex and RwLock instead of lock poisoning, and in catch_unwind to require that the closure only holds/references types that are Consistent/RefConsistent.

That would severely restrict what types could be protected by a mutex. In an ideal would that might work, but there would need to be an escape hatch and get the poisoning behaviour instead. Perhaps via some sort of Mutex<Poisoning<T>>, but I suspect the mutex would need to know about this inner layer.