Hacker News new | past | comments | ask | show | jobs | submit login

This is a great post! One additional thing:

> 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>.




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.


Isn’t that the same in Rust? For example, split_at_mut?

(I mean, it’s not like this is 100% nailed down yet...)


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).


Right, but they both exist. I guess that’s what I’m trying to say... it’s the active bit that matters.


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.


That’s fair, but I feel like split_at_mut is far more well-known than reborrowing.


Doesn't UnsafeCell only affect &T, not &mut T? &mut is always unique.


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.

You still can’t have un-exclusive access with a &mut T. For more: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html

(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.


You won’t get the noalias stuff on &mut T until ththen next release, as I mentioned above, due to an LLVM bug.


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. :)


    Are *const T and *mut T also restrict in C terms? (If not, why not?)


They are not. They’re not because they provide no guarantees; they’re just regular pointers.


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?


I think it makes unsafe code less error prone to write, but additionally it allows you to interop with C APIs that have aliasing pointers.

Also, if they were restrict, it would be UB in rust, which I think is something Rust tries to avoid where possible.


Well, &T is allowed to alias too.

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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: