Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Bound Checks

After desugaring temporaries, the remaining place expressions are mostly side-effect free. The exception is bounds checks. In this step we make bounds checks explicit.

After the previous desugarings, all place expressions are broken into let place bindings, so the only way an indexing expression may show up is as let place q = p[i]; where p and i are bindings.

We desugar this as follows, using Unchecked Indexing:

#![allow(unused)]
fn main() {
let place q = p[i];

// becomes:
let len = core::slice::length(&raw const p);
assert!(i < len, "appropriate message");
let place q = unchecked_index!(p, i);
}

We do something similar for range indexing.

At the end of this step, there are no checked indexing place expressions left.


Discussion

This desugaring is actually unsound if we don't run borrow-checking before doing it:

#![allow(unused)]
fn main() {
let mut x: &[[u32; 1]] = &[[42]];
let _ = &mut x[0][{x = &[]; 0}];

// becomes:
let _ = {
    let i = 0;
    let len = x.len();
    assert!(i < len);
    let p = unchecked_index!(x, i);
    let j = {x = &[]; 0};
    &mut p[j] // out of bounds access
};
}

Rustc rejects this code using borrow-checking tricks. See Borrow Checking.

let place should probably have a way to disallow invalidating a place alias.