& and &mut vs rwlock

How about if we roughly match the behavior of & and &mut with that of rwlock ?

  1. introduce a & is equivalent to acquire reader lock
  2. introduce a &mut is equivalent to acquire a writer lock

if so , the following counter intuitive example won't exist (1 will not going to compile).

// 1
fn main() {
  let mut v=0;
  let a = &mut v;
  let b = &v;
  v=1;         // A
}
// 2
fn main() {
  let mut v=0;
  let a = &mut v;
  let b = &v;
  *a=1;      // B
}

1 didn't used to compile. If you try it in Rust 1.10, you'll see it error:

<source>:4:12: 4:13 error: cannot borrow `v` as immutable because it is also borrowed as mutable [E0502]
<source>:4   let b = &v;
                      ^
<source>:3:16: 3:17 note: mutable borrow occurs here
<source>:3   let a = &mut v;
                          ^
<source>:6:1: 6:2 note: mutable borrow ends here
<source>:6 }
           ^
<source>:4:12: 4:13 help: run `rustc --explain E0502` to see a detailed explanation
<source>:5:3: 5:6 error: cannot assign to `v` because it is borrowed [E0506]
<source>:5   v=1;         // A
             ^~~
<source>:3:16: 3:17 note: borrow of `v` occurs here
<source>:3   let a = &mut v;
                          ^
<source>:5:3: 5:6 help: run `rustc --explain E0506` to see a detailed explanation
error: aborting due to 2 previous errors

That turned out to be a major stumbling block, however, and the rules were tweaked with NLL in 1.31: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#non-lexical-lifetimes

1 Like

Basically, with the current rules, the compiler automatically "unlocks" it at the last use, rather than when it goes out of scope.

3 Likes

and automaticlly "lock" at first use? if so , 2 should compile.

No, at creation of the reference. The creation of a reference is usually considered a use, and the destruction is usually not.

in 2 it seems b's first and last use is at the same line, 2 should compile.

// 2
fn main() {
  let mut v=0;
  let a = &mut v;
  let b = &v;
  *a=1;      // B
}

No. This would deadlock with an rwlock:

let write_guard = lock.write();
let read_guard = lock.read(); // <--- would deadlock here
drop(read_guard);
drop(write_guard);

thanks . this explains why 2 can not compile.

this also explains why 1 compile

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.