Actually, &mut isn't equivalent to restrict, since two restrict pointers are allowed to alias in C as long as none of the intervening accesses are writes.
split_at_mut doesn't allow you to read through aliased "active" &mut pointers either (I would assume that restrict pointers that cannot be either read from or written to don't count).
Hm, in that case you don't need to appeal to split_at_mut--reborrowing is sufficient to demonstrate that point. I think what czwarich is saying is more subtle--that restrict allows "multiple readers, exclusive writer", which means that both shared pointers without UnsafeCell and mutable references in Rust are restrict in this sense, while &mut is more restrictive.
It’s true that &mut T is always unique; restrict says “this does not alias”, which &Ts trivially do. It goes on &mut T. For example, see https://github.com/rust-lang/rust/pull/31545, we had to remove this for a few releases due to an LLVM bug; it'll be back in the next release.
It’s phrased in the reference as
> &mut T and &T follow LLVM’s scoped noalias model, except if the &T contains an UnsafeCell.
“noalias” is restrict here. But it’s not on &T, it’s the system as a whole that follows the guarantees, that is, both with and without.
(And see the stuff on that page about how some of this is still in flux. And, maybe I’ve made some mistake with my words here; this stuff is hard and not what I deal with day to day...)
Right, so if &mut is always unique anyway then the presence of an UnsafeCell shouldn't affect it, since it's about weakening guarantees.
In fact, looking at the compiler output (https://godbolt.org/g/kt2xfW), it looks like only &T has noalias, and not &mut T. It does go away in the presence of UnsafeCell, but for &mut T it was never there in the first place.
So either that's a place where we can still add more noalias annotations, or it's off for some subtle reason I'm not familiar with.
Ah, right; missed that part of what you were saying.
If you switch the compiler version on my godbolt link to beta, the &mut i32 and &mut UnsafeCell<i32> both have the noalias attribute, so looks like it's on track. :)
Aside from the aspect of restrict pointers being a footgun for C programmers who aren't used to them and apart from being able to convert C to unsafe Rust with e.g. Corrode, what use cases (within the scope of things that one has to use unsafe Rust for as opposed to writing C-like code) are there for pointers that are allowed to alias?
Having unchecked pointers is important for Rust to be a systems programming language. But, since they're unchecked, they may alias. That's just the nature of not being able to make guarantees.
That doesn't explain it from the use case perspective. E.g. dereferencing a pointer with asterisk operator requires the pointer to be aligned, so unchecked things can still have requirements that need to be met.
I think the primary reason why Rust doesn't have explicit unsafe restrict pointers is that there's virtually no demand for them (that I've seen, anyway).
Unlike raw pointers with no aliasing restrictions, restrict is used super rarely in C because it's so hard to figure out when it's safe--I think it was only added to make C competitive with Fortran in certain benchmarks. Restrict means you can never alias, so storing one in a data structure is just tempting fate without the aid of the compiler, and if you just need it temporarily casting a * mut to &mut works fine. Rust programs certainly use restrict a lot more than any C program does, and I don't think adding an additional layer of "restrict without a lifetime" would be terribly beneficial in most cases.
> The only differences between borrowed references and raw pointers are:
There’s one more: &mut T is restrict, in C terms, as long as T doesn't contain an UnsafeCell<T>.