For some reason, this compiles without warning (only one that a is not used for the nitpickers)
fn main() {
let mut a = 0;
let b = &raw const a;
a = 1;
unsafe {
println!("{}", *b);
}
}
Output:
1
This is definitely not intended behavior, and I think there should at least be a warning if a const pointer's pointed value changes and then the pointer is referenced.
*const vs *mut only changes the variance over T and prevents direct writes through it, nothing else. In fact, because of the variance effects, people use *const to represent owned values that are very much written through.
The entire point of raw pointers is that they are not checked by a borrow checker.
So this is intended behavior and good.
That said, this is undefined behavior under stacked borrows, not because it's *const, but because writing to the value directly invalidates all pointers to the value. Miri will flag this.
So a lint for the "pointer used after invalidation" case wouldn't be a bad idea, but that's unrelated to the mutability of the pointer.
Wait, why? Is there some piece of documentation or reference that spells out this?
Is this just syntactic restriction? (That is, specifically writes through a aren't allowed, all others are). I mean, surely we can in general have other code changing memory that a raw pointer points to.
Whether or not that code is allowed is an unresolved question. So this code is in the gray area. AFAIK we don't usually lint for that.
Also, there are so many lints we could write for raw pointer misuse... I feel like that needs a somewhat holistic approach, not picking random ad-hoc examples.
I think you have linked the wrong unresolved question? Doing this is disallowed under Stacked Borrows regardless of whether the pointer to b is initially *const or *mut (because the a = 1; line conceptually creates a new mutable borrow of a which conflicts with the pointer, even if the pointer is mutable).
It is still an unresolved question, but a different one, and I haven't immediately been able to tell which one (although it's mentioned in unsafe-code-guidelines issue 573 it isn't the main purpose of that post.
TBH, I'm always skeptical about warnings like this around raw pointers. The whole point of using raw pointers in Rust is doing things that the compiler doesn't understand well, and thus trying to make more and more complicated lints just makes the compiler slower for questionable gain.
It is realistic that people are writing this code instead of using references that do give good diagnostics for things like this? If someone wrote this because the reference-using code didn't compile, a warning won't make them stop either.
The underlying unresolved question is whether raw pointers always get the tag of the place they are created from, or whether they sometimes get their own tag. The issue I linked is a direct consequence of raw pointers getting their own tag in Stacked Borrows. So in that sense it is the same question, though I admit the issue description and discussion doesn't really reflect that. Maybe we should have a separate issue making this more clear.