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 Tmay alias&mut T, even though it's normally allowed to assume that&mut Tnever aliases another&mut T?Does the
unsafeblock 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?
xandx_ptrcontain the address of the same type, LLVM must reloadx