Borrowck 6 @adotinthevoid @Nilstrieb

Warning: this quiz is still "work-in-progress", some questions might not have good explanations (or any at all), formatting/structure/titles/etc are not final, and so on. You might want to return here on a later date.

type R1<'a> = &'a mut i32;
struct R2<'a>(&'a mut i32);

fn r1_once(_: R1){}
fn r2_once(_: R2){}

pub fn r1_twice(x: R1) {
    r1_once(x);
    r1_once(x);
}

pub fn r2_twice(x: R2) {
    r2_once(x);
    r2_once(x);
}

fn main() {
    r1_twice(&mut 0);
    r2_twice(R2(&mut 0));
}
Solution
error[E0382]: use of moved value: `x`
  --> examples/borrowck_6.rs:14:13
   |
12 | pub fn r2_twice(x: R2) {
   |                 - move occurs because `x` has type `R2<'_>`, which does not implement the `Copy` trait
13 |     r2_once(x);
   |             - value moved here
14 |     r2_once(x);
   |             ^ value used here after move
   |
note: consider changing this parameter type in function `r2_once` to borrow instead if owning the value isn't necessary
  --> examples/borrowck_6.rs:5:15
   |
5  | fn r2_once(_: R2){}
   |    -------    ^^ this parameter takes ownership of the value
   |    |
   |    in this function

For more information about this error, try `rustc --explain E0382`.
error: could not compile `code` (example "borrowck_6") due to 1 previous error

r2_twice does not compile because R2 does not implement Copy, and is moved twice. This is basic Rust, but r1_twice does compile even though &mut i32 does not implement Copy! That's because for R1, the reference is not moved into r1_once, it is instead reborrowed. Reborrows are a special operation on references that the borrow checker understands and behave like &mut *x. So there is just a new reference passed to r1_once, with the original one preserved.