Right now if a trait provides a method that is safe, it is impossible to implement that trait with an unsafe method. Now, in general, this makes sense. Generic code has to know if it’s calling a safe function or not. However, this is a problem for magic traits in Rust.
In particular, all the operators in Rust like Deref, Fn, and Index can only be implemented safely. This means that unsafe code has to be more cumbersome to write than safe code, or is special-cased in the compiler (see: derefing rawptrs). Unsafe code is by definition the most important to write correctly. If you have to jump through too many hoops to write it at all, then that could very well reduce your ability to do it correctly.
Therefore, this Pre-RFC proposes the ability to specify an entire impl as unsafe. This would look like:
unsafe impl<T> Deref<T> for *const T {
...
}
This causes the compiler to treat all methods in the impl as unsafe, even the default ones (because they probably call the non-default ones). If a type T implements a trait unsafely, it cannot be offered to a function that is generic over that trait. To opt into allowing unsafe impls, a generic bound can use the Unsafe? modifier. This is exactly analogous to the Sized? modifier: it allows types of either kind, but forces the function to assume that they’re the more restrictive one. In this case, calling any methods on an Unsafe? would be assumed to be unsafe.
fn do_unsafe_work<D: Unsafe? Deref<uint>>(data: D) { ... }
Obviously, this should not be done in general. It should only be done in internal methods where the set of generic implementors and their safety constraints are known. Even then, this is mostly intended to only be used in cases where the type is concrete and known.
Downsides
- More lang items, more complexity
Alternatives
- Just let unsafe code be harder to write/use.
- Provide Unsafe* variants of the language’s magic traits.
- Allow some methods on an unsafe impl to not be unsafe by requiring methods to be individually marked as safe or unsafe. Of course, the compiler has to treat all of the methods as unsafe in a generic context, but in the concrete and documentation context, this can improve ergonomics.