Borrow-checking surprises

The puzzling snippet
A tiny Rust program is causing big confusion. Consider:
`
fn main() {
let mut x = 0;
let y = &mut x;
y = y + 1;
}
`
At first glance this looks illegal. The left-hand side is a mutable place pointing at x, while the right-hand side reads x. Reading while you hold a mutable borrow? That should be a red flag. It has been reported that the author of the original post repeatedly gets surprised by examples like this — and that when shown to others, many offer confidently wrong explanations. Surprise, then disbelief.
Why it actually compiles
The trick is evaluation order and short-lived reborrows. Rust evaluates the right-hand side fully before taking the borrow needed to perform the assignment to the left-hand place. The read (*y on the RHS) happens first, producing a value (an i32 copy) via the existing mutable reference. Only after that read completes does the compiler create whatever temporary borrow is needed to write the result back. In practice the compiler models these as very short, non-overlapping borrows (thanks in part to non-lexical lifetimes), so no two conflicting borrows are considered live at the same time.
So what should you change about your mental model?
Don't assume borrows are always long-lived and global in scope; think about when borrows are created and how long they actually live. Rust’s borrow checker is conservative in the abstract, but the implementation uses reborrows and precise lifetime analysis to allow patterns that look forbidden on paper. It’s a small, elegant twist — and a reminder that with Rust, the hair-raising moments usually come from the gap between your intuition and the language’s precise operational details.
Sources: scattered-thoughts.net, Lobsters
Comments