0

I am learning rust, I am trying to understand references.

As per the rust's book -> https://doc.rust-lang.org/nightly/book/ch04-02-references-and-borrowing.html

It says

Note that a reference’s scope starts from where it is introduced 
and continues through the last time that reference is used.

And goes on showing (from the book):

    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    println!("{} and {}", r1, r2);
    // variables r1 and r2 will not be used after this point !! ... okay..?

BUT when I try to reproduce this, I get no error

My example (no error)

fn valid() {
    let s = String::from("hi");
    
    let r1 = &s; // valid immutable reference
    let r2 = &s; // valid immutable reference
    println!("{}, {}", r1, r2);
    println!("{}", r1); // Why am I able to use r1 again here??
}
Karan Kumar
  • 2,678
  • 5
  • 29
  • 65

2 Answers2

4

Because you have now changed when the "last use" of r1 is to be at the second print.

You decide when the reference should end and you do so by not using it after a given point. If you add a later use, then you have clearly decided on a new "last use" and so the compiler obliges.

Emoun
  • 2,297
  • 1
  • 13
  • 20
2

I think you misunderstood what you read. I'm assuming you're referencing this bit of code in the linked resource:

let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
// variables r1 and r2 will not be used after this point

let r3 = &mut s; // no problem
println!("{}", r3);

The point of the code is that since there is no further use of the shared references r1 and r2 it's okay to take the mutable reference r3. If you try to use one of them after doing so you'll get an error:

let mut s = String::from("hello");

let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);

let r3 = &mut s; // ERROR, no longer after last use of r1
println!("{}", r1);

The point of the example isn't that you can't use r1 and r2 after that line, it's that you cannot take a mutable reference &mut while something is still holding on to a shared reference &.

Playground

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • I'm having the same doubt on the same book, so the error is the last `println` using `r1`? I don't understand "while something is still holding on to a shared reference `&`", because I don't see we 'clear' the reference. – Yuri Aps May 17 '23 at 13:06
  • @YuriAps `r1` is a shared reference to `s` (`&s`). Once it's no longer used the compiler drops it, and you can take a mutable ref to `s` (`r3`, which is to say `&mut s`). But that last print statement uses `r1` so the compiler has to keep `r1` around for it, meaning that `r3` becomes illegal. – Jared Smith May 17 '23 at 13:17
  • In my head it only makes sense if the `printl` is dropping it, if not, how would the compiler know that `r3` can be created? Only if it goes forward and backwards. Is this how compilers work? – Yuri Aps May 17 '23 at 13:35
  • Why would println be dropping anything? The compiler knows from analyzing the source that in the first case the mutable ref is created after the last use of all the shared refs to `s` (the first println is mostly there to avoid getting a warning/error about unused variables) and in the second case it can tell at the point `r3` is created that `r1` is still in play later in that lexical scope. "Only if it goes forward and backwards. Is this how compilers work?" basically yes. – Jared Smith May 17 '23 at 14:00