Search code examples
rust

Why is it allowed to take both an exclusive (mutable) and a shared (immutable) reference to the same object, as long as only one is used?


I have this code snippet which has both mutable and immutable references existing at the same time but still it compiles why ?

let mut str_1 = String::from("Rust");
let ref_1 = &str_1;      // Immutable reference to `str_1`
let ref_2 = &mut str_1;  // Mutable reference to `str_1`
println!("{}", ref_2);

This doesn't compile

let mut str_1 = String::from("Rust");
let ref_1 = &str_1;      // Immutable reference to `str_1`
let ref_2 = &mut str_1;  // Mutable reference to `str_1`
println!("{},{}", ref_2,ref_1);

Is it like unless i don't use the ref_1 in println it will compile?


Solution

  • Because since the non-lexical lifetimes work borrows end as soon as they're not used anymore[0] (rather than at the end of scope as drops do).

    In your first snippet, ref_1 is a dead variable, so the borrow ends as soon as it's created, it's likely the compiler doesn't even create a pointer. Hence on the next line you can borrow str_1 mutably, because the first borrow has already ended (or never existed in the first place).

    In the second snippet however, because ref_1 is used by the println! it has to live until after that macro's execution, thus it overlaps with ref_2, and because the two borrows are not compatible you get a compilation error.


    [0]: kinda, things get more complicated around sub-statement temporaries