3 ms·
> Unless you're talking to hardware or another language, you should not need unsafe code. ... or if you're implementing safe abstractions on top of data struct
by taliesinb 12y ago
> Unless you're talking to hardware or another language, you should not need unsafe code.
... or if you're implementing safe abstractions on top of data structures or synchronization protocols that the type system cannot automatically infer to be safe.
Of course that is going to be a smallish subset of Rust programmers that gets smaller with time as the standard library fills out, but an important one!
For those who aren't as familiar with Rust, the std::sync [0] module can be a fun way to cut your teeth.
For example, here's the implementation of Mutex.lock [1]:
pub fn lock(&self) -> LockResult<MutexGuard<T>> {
unsafe { self.inner.lock.lock() }
MutexGuard::new(&*self.inner, &self.data)
}
Note that the self argument is immutable: "&self" instead of "&mut self". This may seem odd: doesn't locking a mutex require a change to its innards? Which is why you should not be surprised to see the unsafe, which allows us to bend the immutability of &self in order to acquire the lock.
In fact, how could it be otherwise? Rust prevents there ever being more than one &mut to something, so if the signature of Mutex::lock was "&mut self", there could only ever be one usable ref to the Mutex! That would be pointless, of course -- multiple threads need to have references to the mutex.
We're still safe, though, because the "mut-aliasing" that Rust normally prevents via the borrow checker at compile time is being replaced with a run-time mechanism that achieves the same thing via the Mutex and the MutexGuard [2].
[0] http://doc.rust-lang.org/std/sync/index.html http://doc.rust-lang.org/std/sync/index.html
[1] http://doc.rust-lang.org/src/std/sync/mutex.rs.html#196-211 http://doc.rust-lang.org/src/std/sync/mutex.rs.html#196-211
[2] Well, strictly speaking a RwLock is a closer runtime approximation to the borrow checker's rules, because it allows multiple simultaneous readers: http://doc.rust-lang.org/std/sync/struct.RwLock.html http://doc.rust-lang.org/std/sync/struct.RwLock.html
- kibwen 12y agoRust's own Aaron Turon put this nicely in a recent talk at Stanford. A data race requires all of the following: aliasing, mutation, and a lack of synchronization. Rust's usual ownership rules already make aliasing exclusive with mutation, so out of the box you're safe. But when simultaneous aliasing and mutation is exactly what you want, as in a mutex, it's safe to subvert the type system as long as you make sure to uphold the synchronization aspect on your own (which Rust nicely helps with by leveraging ownership on the synchronization mechanism itself). https://www.youtube.com/watch?v=O5vzLKg7y-k&t=31m00s https://www.youtube.com/watch?v=O5vzLKg7y-k&t=31m00s
- Animats 12y agoI was at that talk. In a sense, what you need there is not "unsafe", but "atomic", declaring that the contained operation is atomic. That's less general than "unsafe", and atomicity of code is checkable.