Kobi
Kobi

Reputation: 878

Why does Rust compiler not detecting an unused-borrowed reference?

Why does the following fail to compile (2018 edition)

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    {
        let _r2 = &s;
    }
    println!("{}", r1);
}

Why the compiler fails to notice that _r2 is unused and successfully compile the above? It complains that we have both mutable and immutable refs and mutable is used in println.

Upvotes: 2

Views: 125

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170713

the confusing part is that literature (books etc...) talk about "using block to restrict borrowing scope. "Beginning Rust" p348 for example. So I found it confusing that we advocate for such practices but it (sometimes) does not work.

But it does work here; the scope of _r2 is restricted by the block it's declared in. The problem is just that r1 is visible in this scope as well.

That is, the error message is not saying "you can't println because there are both mutable and immutable borrows at that point", but "you can't declare _r2 because there is already a mutable borrow at that point". println only appears as a reason why r1 is still alive at the point of _r2's declaration.

You can see it from the error message:

error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
 --> src/main.rs:5:19
  |
3 |     let r1 = &mut s;
  |              ------ mutable borrow occurs here
4 |     {
5 |         let _r2 = &s;
  |                   ^^ immutable borrow occurs here
6 |     }
7 |     println!("{}", r1);
  |                    -- mutable borrow later used here

^^ points at the actual error location; -- are other related locations.

Upvotes: 3

Kenedi Novriansyah
Kenedi Novriansyah

Reputation: 7

You can only do like this,

fn main(){
   let mut s = String::from("hello");
   let r1 = &mut s;
   {
      let r2 = &r1;
   }
   println!("{}", r1);
}

Upvotes: -1

Related Questions