Borrow Checker 4 @BoxyUwU @WaffleLapkin

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.

#[derive(Debug)]
struct Foo<'a>(&'a mut u32);

fn main() {
    let mut data = 10;
    let mut foo = Foo(&mut data);
    mutate(&mut foo);
    dbg!(foo);
}

fn mutate<'a>(f: &'a mut Foo<'a>) {
    *f.0 += 1;
}
Solution
error[E0505]: cannot move out of `foo` because it is borrowed
 --> examples/borrowck_4.rs:8:5
  |
6 |     let mut foo = Foo(&mut data);
  |         ------- binding `foo` declared here
7 |     mutate(&mut foo);
  |            -------- borrow of `foo` occurs here
8 |     dbg!(foo);
  |     ^^^^^^^^^
  |     |
  |     move out of `foo` occurs here
  |     borrow later used here
  |
  = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
  |
7 |     mutate(&mut foo).clone();
  |                     ++++++++

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

mutate forces the lifetime of the reference to be the same as the lifetime of the foo itself, so you effectively can't use it ever again — any reference will overlap with the one passed to mutate.

To fix this you need to detach the lifetime of the reference from Foo's lifetime:

fn mutate<'a, 'b>(f: &'a mut Foo<'b>) { ... }

Alternatively you can elide both lifetimes:

fn mutate(f: &mut Foo<'_>) { ... }