Unsafe 3 @orlp @Noratrieb

Warning: this quiz is still "work-in-progress", some questions might not have good explanations (or any at all), formatting/structure/titles/etc are not final, and so on. You might want to return here on a later date.

Note: the question is whether the code, as executed, is UB or whether it is sound. When the snippet has UB, explain exactly where it is UB and why.

fn main() {
    let mut v = vec![0_u8; 10];

    // SAFETY: The vec has 10 elements, so 1 and 2 are in bounds.
    //         The two elements are distinct, so we are not overlapping.
    unsafe {
        let r1: *mut u8 = v.as_mut_ptr().add(1);
        let r2: *mut u8 = v.as_mut_ptr().add(2);
        *r1 = 10;
        *r2 = 10;
    }
}
fn main() {
    let mut v = vec![0_u8; 10];

    // SAFETY: The vec has 10 elements, so 1 and 2 are in bounds.
    //         The two elements are distinct, so we are not overlapping.
    unsafe {
        let r1: *mut u8 = v.get_unchecked_mut(1);
        let r2: *mut u8 = v.get_unchecked_mut(2);
        *r1 = 10;
        *r2 = 10;
    }
}
Solution

Example 1 is sound, example 2 is UB.

error: Undefined Behavior: attempting a write access using <2620> at alloc1189[0x1], but that tag does not exist in the borrow stack for this location
 --> examples/unsafe_3_2.rs:9:9
  |
9 |         *r1 = 10;
  |         ^^^^^^^^
  |         |
  |         attempting a write access using <2620> at alloc1189[0x1], but that tag does not exist in the borrow stack for this location
  |         this error occurs as part of an access at alloc1189[0x1..0x2]
  |
  = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
  = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <2620> was created by a SharedReadWrite retag at offsets [0x1..0x2]
 --> examples/unsafe_3_2.rs:7:27
  |
7 |         let r1: *mut u8 = v.get_unchecked_mut(1);
  |                           ^^^^^^^^^^^^^^^^^^^^^^
help: <2620> was later invalidated at offsets [0x0..0xa] by a Unique retag
 --> examples/unsafe_3_2.rs:8:27
  |
8 |         let r2: *mut u8 = v.get_unchecked_mut(2);
  |                           ^^^^^^^^^^^^^^^^^^^^^^
  = note: BACKTRACE (of the first span):
  = note: inside `main` at examples/unsafe_3_2.rs:9:9: 9:17

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

v.as_mut_ptr() refers to Vec::as_mut_ptr(v), which only creates a &mut reference to the vec itself.

v.get_unchecked_mut() comes from an implicit dereference to a slice, referring to <[T]>::get_unchecked_mut(Vec::deref(v)), creating a &mut to all slice elements. When doing the deref for creating r2, this full &mut invalidates r1.