CodeBlanks Logo Icon CodeBlanks

Summary - Unsafe Rust

Combine unsafe and raw pointers to build split_in_two.

Unsafe Rust summary

unsafe allows five extra operations: dereferencing raw pointers, calling an unsafe fn, accessing a static mut, implementing an unsafe trait and reading a union. The borrow checker stays on. Rules: keep unsafe small, justify every block with // SAFETY:, document the contract of unsafe fns with # Safety and offer a safe interface to the outside. Use cargo miri test for verification.

Safe abstraction: split_at_mut

The standard library's split_at_mut is a safe abstraction built with unsafe. Let's write the same:

use std::slice;

fn ikiye_bol(v: &mut [i32], orta: usize) -> (&mut [i32], &mut [i32]) {
    let n = v.len();
    assert!(orta <= n);
    let p = v.as_mut_ptr();
    // SAFETY: [0, orta) and [orta, n) are disjoint and within v's bounds.
    unsafe {
        (
            slice::from_raw_parts_mut(p, orta),
            slice::from_raw_parts_mut(p.add(orta), n - orta),
        )
    }
}

The assert! guarantees the contract at runtime; that's why the function is safe.

Practice Your own split_at_mut

Write the ikiye_bol function above. For let mut v = [1, 2, 3, 4, 5];, get the two pieces with ikiye_bol(&mut v, 2), set the first element of the first piece to 10 and the first element of the second to 30, then print v.

Starter code

main.rs
use std::slice;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::slice;

fn ikiye_bol(v: &mut [i32], orta: usize) -> (&mut [i32], &mut [i32]) {
    let n = v.len();
    assert!(orta <= n);
    let p = v.as_mut_ptr();
    // SAFETY: [0, orta) ve [orta, n) ayrık ve v'nin sınırları içinde.
    unsafe {
        (
            slice::from_raw_parts_mut(p, orta),
            slice::from_raw_parts_mut(p.add(orta), n - orta),
        )
    }
}

fn main() {
    let mut v = [1, 2, 3, 4, 5];
    let (a, b) = ikiye_bol(&mut v, 2);
    a[0] = 10;
    b[0] = 30;
    println!("{:?}", v);
}

Expected output

[10, 2, 30, 4, 5]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why can't <code>split_at_mut</code> be written in safe code?

  • &mut can't be returned
  • It can be
  • The compiler can't prove that two &mut pieces taken from the same slice don't overlap Correct answer
  • Slices can't be split

Explanation: What's obvious to a human (the two pieces are disjoint) can't be proven by the compiler; here unsafe asks us to supply the proof.

2 Slice from raw parts

Question
slice::____(p.add(orta), n - orta)
Answer
slice::from_raw_parts_mut(p.add(orta), n - orta)

Explanation: from_raw_parts_mut builds a &mut [T] from a pointer and a length.

3 Group summary

Term Meaning
unsafe { } Five extra operations
*const / *mut Raw pointer
extern "C" FFI
assert! + unsafe Safe abstraction

All lessons in Advanced