I don't have a particularly solid understanding of Rust's aliasing rules (and from what I've heard they're not solidly defined), but I'm having trouble understanding what makes this code example in the std::slice
documentation okay. I'll repeat it here:
let x = &mut [1, 2, 4];
let x_ptr = x.as_mut_ptr();
unsafe {
for i in 0..x.len() {
*x_ptr.offset(i as isize) += 2;
}
}
assert_eq!(x, &[3, 4, 6]);
The problem I see here is that x
, being an &mut
reference, can be assumed to be unique by the compiler. The contents of x
get modified through x_ptr
, and then read back via x
, and I see no reason why the compiler couldn't just assume that x
hadn't been modified, since it was never modified through the only existing &mut
reference.
So, what am I missing here?
Is the compiler required to assume that
*mut T
may alias&mut T
, even though it's normally allowed to assume that&mut T
never aliases another&mut T
?Does the
unsafe
block act as some sort of aliasing barrier, where the compiler assumes that code inside it may have modified anything in scope?Is this code example broken?
If there is some kind of stable rule that makes this example okay, what exactly is it? What is its extent? How much should I worry about aliasing assumptions breaking random things in unsafe
Rust code?
x
andx_ptr
contain the address of the same type, LLVM must reloadx
– Kinnon