Copy and reborrows

Shared references (&T) implement Copy, which makes them very flexible. Once you have one, you can have as many as you want; once you've exposed one, you can't keep track of how many there are.

Exclusive references (&mut T) do not implement Copy. Instead, you can use them ergonomically through a mechanism called reborrowing. For example here:

#![allow(unused)]
fn main() {
fn foo<'v>(v: &'v mut Vec<i32>) {
    v.push(0);         // line 1
    println!("{v:?}"); // line 2
}
}

You're not moving v: &mut Vec<i32> when you pass it to push on line 1, or you couldn't print it on line 2. But you're not copying it either, because &mut _ does not implement Copy. Instead *v is reborrowed for some shorter lifetime than 'v, which ends on line 1.

An explicit reborrow would look like this:

#![allow(unused)]
fn main() {
    Vec::push(&mut *v, 0);
}

v can't be used while the reborrow &mut *v exists, but after it "expires", you can use v again. In this way, both &mut are still exclusive borrows.

Though tragically underdocumented, reborrowing is what makes &mut usable; there's a lot of implicit reborrowing in Rust. Reborrowing makes &mut T act like the Copy-able &T in some ways. But the necessity that &mut T is exclusive while it exists leads to it being much less flexible.

Reborrowing is a large topic on its own, but you should at least understand that it exists, and is what enables Rust to be usable and ergonomic while still enforcing memory safety.