Why does modifying a mutable reference's value through a raw pointer not violate Rust's aliasing rules?

巧了我就是萌 提交于 2019-12-04 03:18:31

Disclaimer: there is no formal memory model, yet.1

First of all, I'd like to address:

The problem I see here is that x, being an &mut reference, can be assumed to be unique by the compiler.

Yes... and no. x can only be assumed to be unique if not borrowed, an important distinction:

fn doit(x: &mut T) {
    let y = &mut *x;
    //  x is re-borrowed at this point.
}

Therefore, currently, I would work with the assumption that deriving a pointer from x will temporarily "borrow" x in some sense.

This is all wishy washy in the absence of a formal model, of course, and part of the reason why the rustc compiler is not too aggressive with aliasing optimizations yet: until a formal model is defined, and code is checked to match it, optimizations have to be conservative.

1The RustBelt project is all about establishing a formally proven memory model for Rust. The latest news from Ralf Jung were about a Stacked Borrows model.


From Ralf (comments): the key point in the above example is that there is a clear transfer from x to x_ptr and back to x again. So the x_ptr is a scoped borrow in a sense. Should the usage go x, x_ptr, back to x and back to x_ptr, then the latter would be Undefined Behavior:

fn main() {
    let x = &mut [1, 2, 4];
    let x_ptr = x.as_mut_ptr(); // x_ptr borrows the right to mutate

    unsafe {
        for i in 0..x.len() {
            *x_ptr.offset(i as isize) += 2; // Fine use of raw pointer.
        }
    }
    assert_eq!(x, &[3, 4, 6]);  // x is back in charge, x_ptr invalidated.

    unsafe { *x_ptr += 1; }     // BÄM! Used no-longer-valid raw pointer.
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!